工作单元模式(java)

Posted 小小淘气

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了工作单元模式(java)相关的知识,希望对你有一定的参考价值。

个人理解:工作单元模式是为了解决事务性问题,即保证数据修改提交的一致性。

晚上在看到工作单元模式时,觉得比较有意思,看到的基本都是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 }

这里实现主要的点在于维系一个同一个数据库连接。

以上是关于工作单元模式(java)的主要内容,如果未能解决你的问题,请参考以下文章

我在我的项目中使用带有 PHP 的工作单元设计模式

是否有在单个活动中处理多个片段的 Android 设计模式?

将数据从底部工作表对话框片段传递到片段

MVC3 - Unity/工作单元模式和 Web 服务实现

java 查看寻呼机设计模式与片段。

.NET Core MongoDB数据仓储和工作单元模式封装