Spring嵌套事务解惑(重点)

http://www.iteye.com/topic/35907ui

PROPAGATION_REQUIRED -- 支持当前事务,若是当前没有事务,就新建一个事务。这是最多见的选择。 
PROPAGATION_SUPPORTS -- 支持当前事务,若是当前没有事务,就以非事务方式执行。 
PROPAGATION_MANDATORY -- 支持当前事务,若是当前没有事务,就抛出异常。 
PROPAGATION_REQUIRES_NEW -- 新建事务,若是当前存在事务,把当前事务挂起。 
PROPAGATION_NOT_SUPPORTED -- 以非事务方式执行操做,若是当前存在事务,就把当前事务挂起。 
PROPAGATION_NEVER -- 以非事务方式执行,若是当前存在事务,则抛出异常。 
PROPAGATION_NESTED -- 若是当前存在事务,则在嵌套事务内执行。若是当前没有事务,则进行与PROPAGATION_REQUIRED相似的操做。 
前六个策略相似于EJB CMT,第七个(PROPAGATION_NESTED)是Spring所提供的一个特殊变量。 
它要求事务管理器或者使用JDBC 3.0 Savepoint API提供嵌套事务行为(如Spring的DataSourceTransactionManagerspa

 PROPAGATION_REQUIRES_NEW 启动一个新的, 不依赖于环境的 "内部" 事务. 这个事务将被彻底 commited 或 rolled back 而不依赖于外部事务, 它拥有本身的隔离范围, 本身的锁, 等等. 当内部事务开始执行时, 外部事务将被挂起, 内务事务结束时, 外部事务将继续执行.
  另外一方面, PROPAGATION_NESTED 开始一个 "嵌套的" 事务,  它是已经存在事务的一个真正的子事务. 潜套事务开始执行时,  它将取得一个 savepoint. 若是这个嵌套事务失败, 咱们将回滚到此 savepoint. 潜套事务是外部事务的一部分, 只有外部事务结束后它才会被提交. 事务

PROPAGATION_REQUIRES_NEW 启动一个新的, 不依赖于环境的 "内部" 事务. 这个事务将被彻底 commited 或 rolled back 而不依赖于外部事务, 它拥有本身的隔离范围, 本身的锁, 等等. 当内部事务开始执行时, 外部事务将被挂起, 内务事务结束时, 外部事务将继续执行. 
  另外一方面, PROPAGATION_NESTED 开始一个 "嵌套的" 事务,  它是已经存在事务的一个真正的子事务. 潜套事务开始执行时,  它将取得一个 savepoint. 若是这个嵌套事务失败, 咱们将回滚到此 savepoint. 潜套事务是外部事务的一部分, 只有外部事务结束后它才会被提交. 
  因而可知, PROPAGATION_REQUIRES_NEW 和 PROPAGATION_NESTED 的最大区别在于, PROPAGATION_REQUIRES_NEW 彻底是一个新的事务, 而 PROPAGATION_NESTED 则是外部事务的子事务, 若是外部事务 commit, 潜套事务也会被 commit, 这个规则一样适用于 roll back. get

  因而可知,it

PROPAGATION_REQUIRES_NEW 和 PROPAGATION_NESTED 的最大区别在于,io

PROPAGATION_REQUIRES_NEW 彻底是一个新的事务, 而require

PROPAGATION_NESTED 则是外部事务的子事务, 若是外部事务 commit, 潜套事务也会被 commit,变量

这个规则一样适用于 roll back. 配置

固然, 就算全部嵌套事务都已经成功, 外部事务仍是可能由于嵌套事务的执行结果而致使失败,  此时整个事务都要 roll back ,这也是嵌套事务的重要特性之一, 即外部事务和嵌套事务互相影响程序

只有须要根据子事务的执行状况进行分支处理的状况下才是nested的用武之地, savepoint是嵌套事务回滚的实现方式 须要注意的是使用它的限制条件

使用嵌套事务是有前提的,就是该嵌套事务可能须要作分支处理。不然用 PROPAGATION_REQUIRED 就足够了,若是子事务有异常,直接回滚。

nested 能够在外层rollback全部内层的事务。requiresnew 不行。

例子:

  1. ServiceA {  
  2.       
  3.     /** 
  4.      * 事务属性配置为 PROPAGATION_REQUIRED 
  5.      */  
  6.     void methodA() {  
  7.         ServiceB.methodB();  
  8.     }  
  9.   
  10. }  
  11.   
  12. ServiceB {  
  13.       
  14.     /** 
  15.      * 事务属性配置为 PROPAGATION_REQUIRES_NEW 
  16.      */   
  17.     void methodB() {  
  18.     }  
  19.       
  20. }     

 

PROPAGATION_REQUIRES_NEW 时 ServiceB.methodB 没办法回滚到它执行以前的 SavePoint, 这时已经产生了一些脏数据, 而这些脏数据将可能致使后面的程序执行出错

 

  1. ServiceA {  
  2.       
  3.     /** 
  4.      * 事务属性配置为 PROPAGATION_REQUIRED 
  5.      */  
  6.     void methodA() {  
  7.         try{
  8.         ServiceB.methodB();  
  9.         }catch(Exeception e){
  10.          ServiceC.methodC();
  11.        }
  12.     }  
  13.   
  14. }  
  15.   
  16. ServiceB {  
  17.       
  18.     /** 
  19.      * 事务属性配置为 PROPAGATION_NESTED 
  20.      */   
  21.     void methodB() {  
  22.     }  
  23.       
  24. }     

对于PROPAGATION_NESTED 的嵌套事务而言,若是 ServiceB.methodB()异常,会会回滚到上一个savepoint点,外层事务A,能够捕获,处理ServiceC.methodC(),可是对于ServiceA.methodA()异常,会回滚整个嵌套的事务

相关文章
相关标签/搜索