spring自建事务管理模块。而且这个事务管理是一个抽象设计,可以应用到很多场合,包括普通的DataSource,jta,jms和hibernate上。 



要正确使用spring的事务,首先需要了解spring在事务设计上的一些概念 

统观spring事务,围绕着两个核心PlatformTransactionManager和TransactionStatus



PlatformTransactionManager直译过来就是平台相关事务,这里的平台指的是“事务源”,包括刚才我说的DataSource,jta等等。这些无一不是一个事务源。广义的说,凡是可以完成事务性操作的对象,都可以设计出相对应的PlatformTransactionManager,只要这个事务源支持commit,rollback和getTransaction语意。 



查看spring代码,可以发现这些manager实现事务,就是调用事务源的事务操作方法 



比如 



HibernateTransactionManager

  1. protected void doCommit(DefaultTransactionStatus status); {
  2. HibernateTransactionObject txObject = (HibernateTransactionObject); status.getTransaction();;
  3. if (status.isDebug();); {
  4. logger.debug("Committing Hibernate transaction on session [" +
  5. txObject.getSessionHolder();.getSession(); + "]");;
  6. }
  7. try {
  8. txObject.getSessionHolder();.getTransaction();.commit();;
  9. }
  10. ...
  11. }

jdbc 的DataSourceTransactionManager

  1. protected void doCommit(DefaultTransactionStatus status); {
  2. DataSourceTransactionObject txObject = (DataSourceTransactionObject); status.getTransaction();;
  3. Connection con = txObject.getConnectionHolder();.getConnection();;
  4. if (status.isDebug();); {
  5. logger.debug("Committing JDBC transaction on connection [" + con + "]");;
  6. }
  7. try {
  8. con.commit();;
  9. }
  10. ...
  11. }

那么PlatformTransactionManager以什么依据处理事务呢? 

是TransactionStatus 

查看api发现这个接口有三个方法 

isNewTransaction() ,isRollbackOnly(),setRollbackOnly() 

PlatformTransactionManager就是根据前两个方法决定是否要创建一个新事务,是要递交还是回滚。至于第三个方法是改变事务当前状态的,很多地方都要用到,偏偏PlatformTransactionManager自身好像不怎么用,毕竟事务状态的改变是由程序员代码决定的,不需要一个manager多管闲事。 



总结上面所说的,spring的事务由PlatformTransactionManager管理,manager最后调用事务源的方法来实现一个事务过程。而manager通过TransactionStatus 来决定如何实现。 



接下去说spring事务中的TransactionTemplate和TransactionInterceptor 



TransactionTemplate其实和spring中其他的template的作用类似,起到化简代码的作用,不要被它那么长的名字吓倒了,事实上这个template并不是什么非常核心的对象。如果比较学究派的,可以去看看template设计模式,在此就不再对此赘述了。 

为什么要有TransactionTemplate?先来看看如果没有TransactionTemplate,我们的代码该怎么写 



先来看看spring reference中的一段代码

  1. DefaultTransactionDefinition def = new DefaultTransactionDefinition();
  2. def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);;
  3. TransactionStatus status = transactionManager.getTransaction(def);;
  4. try {
  5. // execute your business logic here
  6. } catch (MyException ex); {
  7. transactionManager.rollback(status);;
  8. throw ex;
  9. }
  10. transactionManager.commit(status);;

这是直接使用transactionManager的例子,可以看到真正执行business logic 的地方是在try当中那段,前后的代码都是为了完成事务管理的。如果每个business logic都要写上那么一段,我肯定是疯了。我们翻出TransactionTemplate的代码看看他怎么化简了我们的代码

  1. public Object execute(TransactionCallback action); throws TransactionException {
  2. TransactionStatus status = this.transactionManager.getTransaction(this);;
  3. Object result = null;
  4. try {
  5. result = action.doInTransaction(status);;
  6. }
  7. catch (RuntimeException ex); {
  8. // transactional code threw application exception -> rollback
  9. rollbackOnException(status, ex);;
  10. throw ex;
  11. }
  12. catch (Error err); {
  13. // transactional code threw error -> rollback
  14. rollbackOnException(status, err);;
  15. throw err;
  16. }
  17. this.transactionManager.commit(status);;
  18. return result;
  19. }

同上面的代码如出一辙,前后是事务处理代码,当中那段result = action.doInTransaction(status);是我们的应用代码。至于action是什么,全看各位的需要了。但是有一点要主要,如果利用TransactionTemplate,那么他不管你扔出什么异常都会回滚事务,但是回滚的是哪个事务呢?继续挖代码

  1. private void rollbackOnException(TransactionStatus status, Throwable ex); throws TransactionException {
  2. if (logger.isDebugEnabled();); {
  3. logger.debug("Initiating transaction rollback on application exception", ex);;
  4. }
  5. try {
  6. this.transactionManager.rollback(status);;
  7. }
  8. catch (RuntimeException ex2); {
  9. logger.error("Application exception overridden by rollback exception", ex);;
  10. throw ex2;
  11. }
  12. catch (Error err); {
  13. logger.error("Application exception overridden by rollback error", ex);;
  14. throw err;
  15. }
  16. }

真相大白,是对template所持有的某个transactionManager进行回滚。所以如果你的应用代码用的是事务源a的一些资源,比如到服务器a的一个datasource,但是你的transactionManager管理的是另一些资源,比如服务器b的一个datasource,代码铁定不会正常运行 



特别是在一些多事务源的程序里,这点千万不能搞错。如果多个事务源之间要完成全局事务,还是老老实实用分布式事务管理服务吧(jta) 



那么TransactionInterceptor是干什么的?这个是spring 的声明式事务的支持方式。因为用TransactionTemplate要硬编码,而且调整事务策略很麻烦(不是说不能调。举个例子原来程序抛出异常A需要回滚,现在不需要要,我就可以把a catch吃掉。这时候template就不会回滚了。但是每次调整都要重写编码。)而用TransactionInterceptor就可以将这些调整写在配置中。我们再来挖TransactionInterceptor的代码

  1. public Object invoke(MethodInvocation invocation); throws Throwable {
  2. // Work out the target class: may be null.
  3. // The TransactionAttributeSource should be passed the target class
  4. // as well as the method, which may be from an interface
  5. Class targetClass = (invocation.getThis(); != null); ? invocation.getThis();.getClass(); : null;
  6. // Create transaction if necessary
  7. TransactionInfo txInfo = createTransactionIfNecessary(invocation.getMethod();, targetClass);;
  8. Object retVal = null;
  9. try {
  10. // This is an around advice.
  11. // Invoke the next interceptor in the chain.
  12. // This will normally result in a target object being invoked.
  13. retVal = invocation.proceed();;
  14. }
  15. catch (Throwable ex); {
  16. // target invocation exception
  17. doCloseTransactionAfterThrowing(txInfo, ex);;
  18. throw ex;
  19. }
  20. finally {
  21. doFinally(txInfo);;
  22. }
  23. doCommitTransactionAfterReturning(txInfo);;
  24. return retVal;
  25. }

万变不离其宗。 



所以使用spring的事务管理需要作这些事 

1,设置好事务源,比如DataSource,hibernate的session。如果有多个事务源要考虑他们之间是否有全局事务,如果有,老老实实用jta,否则就需要自己写一个manager了 

2,设置manager,根据你的事务源选择对应的PlatformTransactionManager 

3,选择实现事物的方式,用template还是interceptor。用template代码直观点,但是template所管辖的manager和你应用代码所用的事务源要一致。如果用interceptor千万注意,一定要调用interceptor那个bean,而不是原始的那个target。在坛子上我已经看到至少有两个朋友说spring事物不起作用,从配置和代码上看都正确,这时要好好查查,调用的bean是哪一个。 

4,这个是设计问题了,推荐事务处于一个较高层次,比如service上的某个函数,而底层的dao可以不考虑事务,否则可能会出现事务嵌套,增加程序复杂度。

spring事务探索的更多相关文章

  1. spring事务传播行为之使用REQUIRES_NEW不回滚

    最近写spring事务时用到REQUIRES_NEW遇到一些不回滚的问题,所以就记录一下. 场景1:在一个服务层里面方法1和方法2都加上事务,其中方法二设置上propagation=Propagati ...

  2. Spring事务专题(五)聊聊Spring事务到底是如何实现的

    前言 本专题大纲: 本文为本专题倒数第二篇文章. 在上篇文章中我们一起学习了Spring中的事务抽象机制以及动手模拟了一下Spring中的事务管理机制,那么本文我们就通过源码来分析一下Spring中的 ...

  3. Mysql事务探索及其在Django中的实践(二)

    继上一篇<Mysql事务探索及其在Django中的实践(一)>交代完问题的背景和Mysql事务基础后,这一篇主要想介绍一下事务在Django中的使用以及实际应用给我们带来的效率提升. 首先 ...

  4. spring事务概念理解

    1.数据并发问题 脏读 A事务读取B事务尚未提交的更新数据,并在此数据的基础上操作.如果B事务回滚,则A事务读取的数据就是错误的.即读取了脏数据或者错误数据. 不可重复组 A事务先后读取了B事务提交[ ...

  5. 【Java EE 学习 52】【Spring学习第四天】【Spring与JDBC】【JdbcTemplate创建的三种方式】【Spring事务管理】【事务中使用dbutils则回滚失败!!!??】

    一.JDBC编程特点 静态代码+动态变量=JDBC编程. 静态代码:比如所有的数据库连接池 都实现了DataSource接口,都实现了Connection接口. 动态变量:用户名.密码.连接的数据库. ...

  6. Spring事务

    1.@Transactional 只能被应用到public方法上, 对于其它非public的方法,如果标记了@Transactional也不会报错,但方法没有事务功能.@Transactional 的 ...

  7. spring事务管理器设计思想(二)

    上文见<spring事务管理器设计思想(一)> 对于第二个问题,涉及到事务的传播级别,定义如下: PROPAGATION_REQUIRED-- 如果当前没有事务,就新建一个事务.这是最常见 ...

  8. spring事务管理器设计思想(一)

    在最近做的一个项目里面,涉及到多数据源的操作,比较特殊的是,这多个数据库的表结构完全相同,由于我们使用的ibatis框架作为持久化层,为了防止每一个数据源都配置一套规则,所以重新实现了数据源,根据线程 ...

  9. Spring事务管理的三种方式

    一 .第一种:全注解声明式事务 Xml代码 复制代码 收藏代码 .<?xml version="1.0" encoding="UTF-8"?> .& ...

随机推荐

  1. UNIX网络编程——线程池模式比较(ICE线程池模型和L/F领导者跟随者模式)

    程池模式一般分为两种:L/F领导者与跟随者模式.HS/HA半同步/半异步模式. HS/HA 半同步/ 半异步模式 :分为三层,同步层.队列层.异步层,又称为生产者消费者模式,主线程处理I/O事件并解析 ...

  2. 错误 frm-40654 记录已经被另一个用户更新,重新查询以查看修改

     导致这问题的原因有多个,有些是最近在项目上发现不同于网上其他人遇到的 网上一般来说大家都说有如下几个原因.但是在项目上做返利时 对AP invoice 的有做更改,导致更改或插入的数据在界面上修 ...

  3. 看人装X,我就来气,开启极限装X模式

    本文书写,纯属扯淡,请勿观看 4进制比二进制更合理,在01的状态中添加了两种状态,从无到有和从有到无的两种过度状态. 如果非要用数值表示,用概率表示.01作为近代计算机的基础,但终究淘汰,构成下一代计 ...

  4. (NO.00004)iOS实现打砖块游戏(六):反弹棒类

    大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请告诉我,如果觉得不错请多多支持点赞.谢谢! hopy ;) 打砖块游戏另一个要素是反弹棒,我们在这篇类来实现反弹棒类. 创建 ...

  5. 1025. PAT Ranking (25)

    题目如下: Programming Ability Test (PAT) is organized by the College of Computer Science and Technology ...

  6. 11、Libgdx的音频

    (官网:www.libgdx.cn) Libgdx提供了简单的方法对较小的音效和磁盘中的音乐进行回放.它同样也提供了方便的针对音频硬件的读写权限. 所有的音频操作都通过audio模块来完成: Audi ...

  7. 小强的HTML5移动开发之路(18)——HTML5地理定位

    来自:http://blog.csdn.net/dawanganban/article/details/18192091 在前面的<小强的HTML5移动开发之路(2)--HTML5的新特性> ...

  8. 【leetcode82】Linked List Cycle

    题目描述: 判断有序list是不是环 要求: 时间复杂度o(n) 原文描述: Given a linked list, determine if it has a cycle in it. Follo ...

  9. android 签名

    (1)Android Studio菜单Build->Generate Signed APK (2)弹出窗口 (3)创建密钥库及密钥,创建后会自动选择刚创建的密钥库和密钥(已拥有密钥库跳过)    ...

  10. How to SetUp The Receiving Transaction Manager

    In this Document   Goal   Solution   References APPLIES TO: Oracle Inventory Management - Version: 1 ...