zoukankan      html  css  js  c++  java
  • [zt]spring本地事务与JTA事务实现解析

    zt:http://www.blogjava.net/luoqx/archive/2006/01/11/16451.html

    大家都知道spring支持两种事务,一种是本地连接事务(使用DataSourceTransactionManager),一种是JTA事务(使用JtaTransactionManager)。并且支持声明式事务和编程式事务两种方式。采用声明式事务使用AOP方式的TransactionProxyFactoryBean代理工厂类。
          JTA事务实现相对较好理解,在执行实际类的符合模式的方法时,代理类通过在连接点前后插入预处理过程(开始事务)和后处理过程(commit或rollbak)即可。因为JTA事务支持两阶段提交所以在代码中启动多少个连接(不同的connection)都能保证事务最终提交或者回滚。可是本地连接事务是如何实现的呢?因为必须后面的dao层必须使用的同一个连接才能保证事务正常提交和回滚,在业务逻辑层可以调用dao层的多个类的多个方法,每个方法如果显式的将connection做为参数传入到还可以,但是这样connection就要出现调用的在业务逻辑层,而且dao的每个方法还要有个connection参数比较难看,而且开发人员要关注事务,这样就没有达到开发人员只要关注业务逻辑即可的要求。 
          web应用,各个类都要在多线程环境下运行,所以每个方法要保证线程安全,这样,不在dao方法中加参数而是在dao类中加入connection属性也就不可取了,怎么办?查看一下JdbcTemplate类,在执行每个方法需要数据库连接时都使用了DataSourceUtils.getConnection(getDataSource())方法?难道每回都从数据源里面取一条连接?不可能,这样事务肯定没法实现,可是怎么能保证取的是一条连接呢?对了是不是采用本地线程呀(TreadLocal),因为一段事务都是在一个线程中完成,所以只要在事务开始的时候将connection存放在本地线程中,然后事务过程中从本地线程中取出connection,直到事务结束即可。不错,这样只需要在每个dao方法的取数据库连接的方法中有个事务状态的判断即可。不错看看spring是不是这样实现的?果然如此,DataSourceUtils.getConnection(DataSource)方法调用doGetConnection()方法,方法内容如下:
    public static Connection doGetConnection(DataSource dataSource) throws SQLException {
      Assert.notNull(dataSource, "No DataSource specified");

      ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(dataSource);
      if (conHolder != null) {
       conHolder.requested();
       return conHolder.getConnection();
      }

      logger.debug("Fetching JDBC Connection from DataSource");
      Connection con = dataSource.getConnection();

      if (TransactionSynchronizationManager.isSynchronizationActive()) {
       logger.debug("Registering transaction synchronization for JDBC Connection");
       // Use same Connection for further JDBC actions within the transaction.
       // Thread-bound object will get removed by synchronization at transaction completion.
       conHolder = new ConnectionHolder(con);
       conHolder.setSynchronizedWithTransaction(true);
       conHolder.requested();
       TransactionSynchronizationManager.registerSynchronization(
         new ConnectionSynchronization(conHolder, dataSource));
       TransactionSynchronizationManager.bindResource(dataSource, conHolder);
      }

      return con;
     }
    conHolder?TransactionSynchronizationManager?很象呀,继续看看TransactionSynchronizationManager类果真如此,里面使用TreadLocal来保存数据连接和事务状态。原来如此,代码里的各个层没有特殊需要都不用再出现事务了,程序开发人员只要关注业务就可以了,不用再劳心编写事务代码了。


    -----------------------------
    這篇文章可以結合本blog中的<<学习编译更好的 DAO 的技巧 >>,這樣可以更加了解dao,以及spring

  • 相关阅读:
    视频笔记
    【LeetCode】给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度
    getopt函数用法
    一些常用的算法库
    c语言结构体
    C语言中time_t数据类型详细介绍
    c语言 static的用法
    C语言中extern的用法
    MATLAB textread函数
    正则表达式
  • 原文地址:https://www.cnblogs.com/oisiv/p/667057.html
Copyright © 2011-2022 走看看