博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
spring事务探索
阅读量:5232 次
发布时间:2019-06-14

本文共 5489 字,大约阅读时间需要 18 分钟。

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

要正确使用spring的事务,首先需要了解spring在事务设计上的一些概念 
统观spring事务,围绕着两个核心PlatformTransactionManager和TransactionStatus

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

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

比如 

HibernateTransactionManager 

 

Java代码   
  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.   
  12.     }  




jdbc 的DataSourceTransactionManager 

Java代码   
  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中的一段代码 

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


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

Java代码   
  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,那么他不管你扔出什么异常都会回滚事务,但是回滚的是哪个事务呢?继续挖代码 

Java代码   
  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的代码 

Java代码   
  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.           
  7.         // Create transaction if necessary  
  8.         TransactionInfo txInfo = createTransactionIfNecessary(invocation.getMethod();, targetClass);;  
  9.   
  10.         Object retVal = null;  
  11.         try {  
  12.             // This is an around advice.  
  13.             // Invoke the next interceptor in the chain.  
  14.             // This will normally result in a target object being invoked.  
  15.             retVal = invocation.proceed();;  
  16.         }  
  17.         catch (Throwable ex); {  
  18.             // target invocation exception  
  19.             doCloseTransactionAfterThrowing(txInfo, ex);;  
  20.             throw ex;  
  21.         }  
  22.         finally {  
  23.             doFinally(txInfo);;  
  24.         }  
  25.         doCommitTransactionAfterReturning(txInfo);;  
  26.   
  27.         return retVal;  
  28.     }  


万变不离其宗。 

所以使用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可以不考虑事务,否则可能会出现事务嵌套,增加程序复杂度。

转载于:https://www.cnblogs.com/baiduligang/p/4246985.html

你可能感兴趣的文章
限制文本框只能输入数字||只能是数字和小数点||只能是整数和浮点数
查看>>
@Transactionl注解
查看>>
Mysql 慢查询和慢查询日志分析
查看>>
编程的修炼(中英双语)
查看>>
JTS空间分析工具包(GIS开源)学习 JAVA
查看>>
实现对称加密及非对称公钥加密
查看>>
Oracle Null 与 in, exists 的关系说明(not in 查不到结果)
查看>>
一个vue小demo购物车
查看>>
javascript 获取滚动条高度+常用js页面宽度与高度[转]
查看>>
nexus admin 从文件角度进行密码重置
查看>>
2012TI杯电子设计大赛
查看>>
[教程]Delphi 中三种回调函数形式解析
查看>>
HeatMap(热图)的原理和实现
查看>>
[转]室友靠打游戏拿30万offer,秘密竟然是……
查看>>
linux下python2.7.x版本安装
查看>>
Laravel5.5 GraphQL 为应用程序构建API
查看>>
IOS框架和服务
查看>>
[转]快速排序 挖坑讲解方法
查看>>
[转]STL之list容器详解
查看>>
python 创建虚拟环境时报错OSError, setuptools下载失败
查看>>