(未使用AOP)使用ThreadLocal对象把Connection和当前线程绑定, 从而使一个线程中只有一个能控制事务的对象

每个连接都有自己的独立事务,会造成数据的不一致

这组操作应该要么一起操作成功,要么一起操作失败, 应该使用同一个连接,只有一个能控制事务的对象

需要使用ThreadLocal对象把Connection和当前线程绑定, 从而使一个线程中只有一个能控制事务的对象

关于ThreadLocal: Java并发编程:深入剖析ThreadLocal

事务控制应该都是在业务层

创建一个连接的工具类,它用于从数据源中获取一个连接,并且实现和线程的绑定

/**
 * 连接的工具类,它用于从数据源中获取一个连接,并且实现和线程的绑定
 */
public class ConnectionUtils {

    private ThreadLocal<Connection> tl = new ThreadLocal<Connection>();
    private DataSource dataSource;

    public void setDataSource(DataSource dataSource) {
        this.dataSource = dataSource;
    }

    /**
     * 获取当前线程上的连接
     * @return
     */
    public Connection getThreadConnection() {
        try{
            //1.先从ThreadLocal上获取
            Connection conn = tl.get();
            //2.判断当前线程上是否有连接
            if (conn == null) {
                //3.从数据源中获取一个连接,并且存入ThreadLocal中
                conn = dataSource.getConnection();
                tl.set(conn);
            }
            //4.返回当前线程上的连接
            return conn;
        }catch (Exception e){
            throw new RuntimeException(e);
        }
    }

    /**
     * 把连接和线程解绑
     */
    public void removeConnection(){
        tl.remove();//remove()用来移除当前线程中变量的副本
  } 
}

  和事务管理相关的工具类,它包含了,开启事务,提交事务,回滚事务和释放连接

 1 /**
 2  * 和事务管理相关的工具类,它包含了,开启事务,提交事务,回滚事务和释放连接
 3  */
 4 public class TransactionManager {
 5 
 6     private ConnectionUtils connectionUtils;
 7 
 8     public void setConnectionUtils(ConnectionUtils connectionUtils) {
 9         this.connectionUtils = connectionUtils;
10     }
11 
12     /**
13      * 开启事务
14      */
15     public  void beginTransaction(){
16         try {
17             connectionUtils.getThreadConnection().setAutoCommit(false);
18         }catch (Exception e){
19             e.printStackTrace();
20         }
21     }
22 
23     /**
24      * 提交事务
25      */
26     public  void commit(){
27         try {
28             connectionUtils.getThreadConnection().commit();
29         }catch (Exception e){
30             e.printStackTrace();
31         }
32     }
33 
34     /**
35      * 回滚事务
36      */
37     public  void rollback(){
38         try {
39             connectionUtils.getThreadConnection().rollback();
40         }catch (Exception e){
41             e.printStackTrace();
42         }
43     }
44 
45 
46     /**
47      * 释放连接
48      */
49     public  void release(){
50         try {
51             connectionUtils.getThreadConnection().close();//还回连接池中
52             connectionUtils.removeConnection();
53         }catch (Exception e){
54             e.printStackTrace();
55         }
56     }
57 }
 1 public class AccountDaoImpl implements IAccountDao {
 2 
 3     private QueryRunner runner;
 4     private ConnectionUtils connectionUtils;
 5 
 6     public void setRunner(QueryRunner runner) {
 7         this.runner = runner;
 8     }
 9 
10     public void setConnectionUtils(ConnectionUtils connectionUtils) {
11         this.connectionUtils = connectionUtils;
12     }
13 
14     public List<Account> findAllAccount() {
15         try{
16             return runner.query(connectionUtils.getThreadConnection(),"select * from account",new BeanListHandler<Account>(Account.class));
17         }catch (Exception e) {
18             throw new RuntimeException(e);
19         }
20     }
21 }
原文地址:https://www.cnblogs.com/mkl7/p/10688173.html