个人理解:工作单元模式是为了解决事务性问题,即保证数据修改提交的一致性。
晚上在看到工作单元模式时,觉得比较有意思,看到的基本都是c#实现的,本着学习的态度,使用java语言实现,实现出来才发现有点蹩脚,权当记录,有时间再完善。
1 package com.xiaolu.unitofwork; 2 3 import com.xiaolu.domain.AggrateRoot; 4 import com.xiaolu.repository.UnitOfWorkRepository; 5 6 /** 7 * @author : xiaolu 2018年2月5日 8 * @todo : 工作单元接口 9 */ 10 public interface UnitOfWork { 11 public void registerAdd(AggrateRoot root, UnitOfWorkRepository repository); 12 13 public void registerModify(AggrateRoot root, UnitOfWorkRepository repository); 14 15 public void registerDelete(AggrateRoot root, UnitOfWorkRepository repository); 16 17 public void commit(); 18 }
1 package com.xiaolu.unitofworkimpl; 2 3 import java.sql.Connection; 4 import java.sql.SQLException; 5 import java.util.HashMap; 6 import java.util.Map; 7 8 import com.xiaolu.datasource.DataSource; 9 import com.xiaolu.domain.AggrateRoot; 10 import com.xiaolu.repository.UnitOfWorkRepository; 11 import com.xiaolu.unitofwork.UnitOfWork; 12 13 public class UnitOfWorkImpl implements UnitOfWork { 14 private Map<AggrateRoot, UnitOfWorkRepository> addMaps = new HashMap<AggrateRoot, UnitOfWorkRepository>(); 15 private Map<AggrateRoot, UnitOfWorkRepository> deleteMaps = new HashMap<AggrateRoot, UnitOfWorkRepository>(); 16 private Map<AggrateRoot, UnitOfWorkRepository> modifyMaps = new HashMap<AggrateRoot, UnitOfWorkRepository>(); 17 18 @Override 19 public void registerAdd(AggrateRoot root, UnitOfWorkRepository repository) { 20 if (!addMaps.containsKey(root)) { 21 this.addMaps.put(root, repository); 22 } 23 } 24 25 @Override 26 public void registerModify(AggrateRoot root, UnitOfWorkRepository repository) { 27 if (!modifyMaps.containsKey(root)) { 28 this.modifyMaps.put(root, repository); 29 } 30 } 31 32 @Override 33 public void registerDelete(AggrateRoot root, UnitOfWorkRepository repository) { 34 if (!deleteMaps.containsKey(root)) { 35 this.deleteMaps.put(root, repository); 36 } 37 } 38 39 @Override 40 public void commit() { 41 // 在这里稍微卡顿了,c#中可以方便的使用TransactionScope事务域,但是java中没有这个概念 42 // 而事务性是建立在数据库链接的基础上,如果这里的添加,删除,修改使用的不是同一个数据库链接 43 // 那么就无法保证其事务性 44 45 Connection conn = DataSource.getConnection(); 46 try { 47 conn.setAutoCommit(false); 48 doCommit(conn); 49 conn.commit(); 50 } catch (SQLException e) { 51 try { 52 conn.rollback(); 53 } catch (SQLException e1) { 54 e1.printStackTrace(); 55 } 56 } finally { 57 // 这里不太舒服,更好的方式是实现java.sql.Connection接口,对原始Connection做一个封装(间接层) 58 DataSource.close(); 59 } 60 } 61 62 private void doCommit(Connection conn) { 63 for (AggrateRoot root : addMaps.keySet()) { 64 addMaps.get(root).doPut(conn, root); 65 } 66 67 for (AggrateRoot root : modifyMaps.keySet()) { 68 modifyMaps.get(root).doModify(conn, root); 69 } 70 71 for (AggrateRoot root : deleteMaps.keySet()) { 72 deleteMaps.get(root).doRemove(conn, root); 73 } 74 } 75 }
package com.xiaolu.domain; /** * @author : xiaolu 2018年2月5日 * @todo : 语义标记接口 */ public interface AggrateRoot { }
package com.xiaolu.repository; import java.sql.Connection; import com.xiaolu.domain.AggrateRoot; import com.xiaolu.unitofwork.UnitOfWork; import com.xiaolu.unitofworkimpl.UnitOfWorkImpl; public abstract class UnitOfWorkRepository { private UnitOfWork work = new UnitOfWorkImpl(); public void put(AggrateRoot root) { work.registerAdd(root, this); } public void modify(AggrateRoot root) { work.registerModify(root, this); } public void remove(AggrateRoot root) { work.registerDelete(root, this); } // 实现中不能关闭连接--- public abstract void doPut(Connection conn, AggrateRoot root); // 实现中不能关闭连接--- public abstract void doModify(Connection conn, AggrateRoot root); // 实现中不能关闭连接--- public abstract void doRemove(Connection conn, AggrateRoot root); }
1 package com.xiaolu.domain; 2 3 public class Account implements AggrateRoot { 4 private int id; 5 // 仅作示例 6 private int money; 7 8 public int getId() { 9 return id; 10 } 11 12 public void setId(int id) { 13 this.id = id; 14 } 15 16 public int getMoney() { 17 return money; 18 } 19 20 public void setMoney(int money) { 21 this.money = money; 22 } 23 24 public void add(int money) { 25 if (money > 0) { 26 this.money += money; 27 } 28 } 29 30 public void minus(int money) { 31 if (this.money >= money) { 32 this.money -= money; 33 } 34 } 35 36 }
1 package com.xiaolu.datasource; 2 3 import java.sql.Connection; 4 import java.sql.SQLException; 5 6 public class DataSource { 7 private static Connection conn = null; 8 9 private DataSource() { 10 } 11 12 // 不考虑多线程的情况 13 public static Connection getConnection() { 14 if (conn == null) { 15 // 创建链接---或者从连接池拿 16 } 17 18 return conn; 19 } 20 21 public static void close() { 22 try { 23 if (conn != null) { 24 conn.close();// 关闭或放回连接池中 25 } 26 } catch (SQLException e) { 27 e.printStackTrace(); 28 } finally { 29 conn = null; 30 } 31 } 32 }
1 package com.xiaolu.service; 2 3 import com.xiaolu.domain.Account; 4 import com.xiaolu.repository.UnitOfWorkRepository; 5 import com.xiaolu.unitofwork.UnitOfWork; 6 7 public class TranslateAccountService { 8 private UnitOfWork work; 9 private UnitOfWorkRepository repository; 10 11 public TranslateAccountService(UnitOfWork work, UnitOfWorkRepository repository) { 12 this.work = work; 13 this.repository = repository; 14 } 15 16 public void translate(Account from, Account to, int money) { 17 // 省略验证 18 19 from.minus(money); 20 to.add(money); 21 22 repository.modify(from); 23 repository.modify(to); 24 25 work.commit(); 26 } 27 }
这里实现主要的点在于维系一个同一个数据库连接。