• (未使用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 }
  • 相关阅读:
    html笔记3
    html笔记2
    html学习第一天
    用Vue中的指令写一个对表格进行增加和删除
    Vue中的列表渲染
    Vue中的计算属性(computed)和侦听器(watch)
    Vue的模块语法
    vue-cli的搭建
    Vue的概念介绍
    React中函数组件和类组件的区别
  • 原文地址:https://www.cnblogs.com/mkl7/p/10688173.html
Copyright © 2020-2023  润新知