工作单元模式

工作单元的定义是:维护一个受业务事务影响的对象列表,并协调写入更改内容和并发问题的解决方案。

一个业务事务中,可能需要多次修改对象模型,对象模型的修改需要记录到数据库中,当然可以每次对象模型有修改时就将变化记录到数据库中,但是这会产生很多对数据库的调用。而使用工作单元来记录业务事务中对数据库有影响的所有变化,就可以减少对数据库的大量小规模调用。

很显然对象模型的变化,工作单元都必须知道并且记录。所以一旦有变化产生都必须通知工作单元,有三种方式来实现:

1. 调用者注册: 

 一旦调用者修改了某个对象,就必须向工作单元注册这个修改。

先写一个工作单元接口

package test.hella.unitwork;

public interface IUnitOfWork{

    void registerAdded(Object entity);
    void registerChanged(Object entity);
    void registerRemoved(Object entity);
    void commit();

}

 然后是接口实现:

package test.hella.unitwork;

import java.util.ArrayList;
import java.util.List;

public class UnitOfWork implements IUnitOfWork {

    private List<Object> newObjects = new ArrayList<Object>();
    private List<Object> dirtyObjects = new ArrayList<Object>();
    private List<Object> removedObjects = new ArrayList<Object>();
    public void registerAdded(Object entity) {
        newObjects.add(entity);
    }
    public void registerChanged(Object entity) {
        dirtyObjects.add(entity);
    }
    public void registerRemoved(Object entity) {
        removedObjects.add(entity);
    }
    public void commit() {
        insertNew();
        updateDirty();
        deleteRemoved();
    }
    private void insertNew() {
        for (Object newObj : newObjects) {
            //DO insert
        }
    }
    private void updateDirty() {
        for (Object dirtyObj : dirtyObjects) {
            //DO update
        }
    }
    private void deleteRemoved() {
        for (Object removedObj : removedObjects) {
            //DO delete
        }
    }

}

 调用着的调用方式:

package test.hella.unitwork;

public class UnitOfWorkTest {
    private static final UserRepository userRepository = new UserRepository();
    public static void main(String[] args) {
        User user1 = new User(1,"user1");
        IUnitOfWork unitOfWork = new UnitOfWork();
        unitOfWork.registerRemoved(user1);
        User user2 = userRepository.getUser(2);
        user2.changeName("user2Changed");
        unitOfWork.registerChanged(user2);
        User user3 = userRepository.getUser(3);
        unitOfWork.registerRemoved(user3);
        unitOfWork.commit();
    }

}

 2. 对象注册:

对象注册的方式,调用者无需负责注册,注册方法被置于对象方法中。

还以上面的代码距离,此时User对象需要负责注册:

扫描二维码关注公众号,回复: 623831 查看本文章
package test.hella.unitwork;

public class User {

    private final long id;
    private String name;
    public long getId() {
        return id;
    }
    public User(long id, String name) {
        this.id = id;
        this.name = name;
    }
    public void changeName(String name, IUnitOfWork unitOfWork) {
        this.name = name;
        unitOfWork.registerChanged(this);
    }

}

 调用者无需再向工作单元进行注册。很明显看到上例中需要将工作单元传递给User对象,这种传递显得不够简洁,更好的方式是将工作单元放到一个众所周知的地方来解决这个问题,比如java的ThreadLocal。

package test.hella.unitwork;

import java.util.ArrayList;
import java.util.List;

public class UnitOfWork implements IUnitOfWork {

    private List<Object> newObjects = new ArrayList<Object>();
    private List<Object> dirtyObjects = new ArrayList<Object>();
    private List<Object> removedObjects = new ArrayList<Object>();
    private static ThreadLocal current = new ThreadLocal<UnitOfWork>();
    public static void newCurrent() {
        setCurrent(new UnitOfWork());
    }
    public static void setCurrent(UnitOfWork now) {
        current.set(now);
    }
    public static UnitOfWork getCurrent() {
        return (UnitOfWork) current.get();
    }
    public void registerAdded(Object entity) {
        newObjects.add(entity);
    }
    public void registerChanged(Object entity) {
        dirtyObjects.add(entity);
    }
    public void registerRemoved(Object entity) {
        removedObjects.add(entity);
    }
    public void commit() {
        insertNew();
        updateDirty();
        deleteRemoved();
    }
    private void insertNew() {
        for (Object newObj : newObjects) {
            //DO insert
        }
    }
    private void updateDirty() {
        for (Object dirtyObj : dirtyObjects) {
            //DO update
        }
    }
    private void deleteRemoved() {
        for (Object removedObj : removedObjects) {
            //DO delete
        }
    }
    
}

3. 工作单元控制器:

这种方式调用者和DomainObject都无需小心翼翼的记得向工作单元注册变化。工作单元控制所有的数据读取,读取数据之后会产生一个拷贝,提交时按照对象的唯一标识和拷贝的对象进行对比,如果有变化则更新数据库中的数据。

 

 

猜你喜欢

转载自hella.iteye.com/blog/1839212