spring事务探索

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

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

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

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

比如 

HibernateTransactionManager 

java代码: 

protected  void doCommit (DefaultTransactionStatus status )  { 
                HibernateTransactionObject txObject =  (HibernateTransactionObject ) status. getTransaction ( ); 
                 if  (status. isDebug ( ) )  { 
                        logger. debug ("Committing Hibernate transaction on session  [" + 
                                        txObject. getSessionHolder ( ). getSession ( ) + " ]" ); 
                 } 
                 try  { 
                        txObject. getSessionHolder ( ). getTransaction ( ). commit ( ); 
                 } 
... 

         }




jdbc 的DataSourceTransactionManager 
java代码: 

protected  void doCommit (DefaultTransactionStatus status )  { 
                DataSourceTransactionObject txObject =  (DataSourceTransactionObject ) status. getTransaction ( ); 
                 Connection con = txObject. getConnectionHolder ( ). getConnection ( ); 
                 if  (status. isDebug ( ) )  { 
                        logger. debug ("Committing JDBC transaction on connection  [" + con + " ]" ); 
                 } 
                 try  { 
                        con. commit ( ); 
                 } 
                ... 
         }




那么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代码: 

DefaultTransactionDefinition def =  new DefaultTransactionDefinition ( ) 
def. setPropagationBehavior (TransactionDefinition. PROPAGATION_REQUIRED ); 

TransactionStatus status = transactionManager. getTransaction (def ); 

try  { 
     // execute your business logic here 
}  catch  (MyException ex )  { 
    transactionManager. rollback (status ); 
    throw ex; 

transactionManager. commit (status );


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

java代码: 

public  Object execute (TransactionCallback action )  throws TransactionException  { 
                TransactionStatus status = this. transactionManager. getTransaction (this ); 
                 Object result =  null; 
                 try  { 
                        result = action. doInTransaction (status ); 
                 } 
                 catch  ( RuntimeException ex )  { 
                         // transactional code threw application exception -> rollback 
                        rollbackOnException (status, ex ); 
                        throw ex; 
                 } 
                 catch  ( Error err )  { 
                         // transactional code threw error -> rollback 
                        rollbackOnException (status, err ); 
                        throw err; 
                 } 
                this. transactionManager. commit (status ); 
                 return result; 
         }



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

private  void rollbackOnException (TransactionStatus status,  Throwable ex )  throws TransactionException  { 
                 if  (logger. isDebugEnabled ( ) )  { 
                        logger. debug ("Initiating transaction rollback on application exception", ex ); 
                 } 
                 try  { 
                        this. transactionManager. rollback (status ); 
                 } 
                 catch  ( RuntimeException ex2 )  { 
                        logger. error ("Application exception overridden by rollback exception", ex ); 
                        throw ex2; 
                 } 
                 catch  ( Error err )  { 
                        logger. error ("Application exception overridden by rollback error", ex ); 
                        throw err; 
                 } 
         }


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

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

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

java代码: 

public  Object invoke (MethodInvocation invocation )  throws  Throwable  { 
                 // Work out the target class: may be null. 
                 // The TransactionAttributeSource should be passed the target class 
                 // as well as the method, which may be from an interface 
                 Class targetClass =  (invocation. getThis ( ) !=  null ) ? invocation. getThis ( ). getClass ( ) :  null; 
                
                 // Create transaction if necessary 
                TransactionInfo txInfo = createTransactionIfNecessary (invocation. getMethod ( ), targetClass ); 

                 Object retVal =  null; 
                 try  { 
                         // This is an around advice. 
                         // Invoke the next interceptor in the chain. 
                         // This will normally result in a target object being invoked. 
                        retVal = invocation. proceed ( ); 
                 } 
                 catch  ( Throwable ex )  { 
                         // target invocation exception 
                        doCloseTransactionAfterThrowing (txInfo, ex ); 
                        throw ex; 
                 } 
                 finally  { 
                        doFinally (txInfo ); 
                 } 
                doCommitTransactionAfterReturning (txInfo ); 

                 return retVal; 
         }


万变不离其宗。 

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

 

http://blog.csdn.net/nimeimei/archive/2005/09/14/480641.aspx

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值