欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

关于spring事务传播特性的相关问题的解释

程序员文章站 2022-06-07 12:58:34
...

      昨天帮助同事解决一个问题,其中遇到一个问题涉及到spring的事务,当时有点不敢肯定,做了实验,并参考了其他同仁的,做了些总结,希望能帮助到大家。

 
我们首先先来看下spring的事务的传播特性:

事务传播行为类型

说明

PROPAGATION_REQUIRED

如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。这是最常见的选择。

PROPAGATION_SUPPORTS

支持当前事务,如果当前没有事务,就以非事务方式执行。

PROPAGATION_MANDATORY

使用当前的事务,如果当前没有事务,就抛出异常。

PROPAGATION_REQUIRES_NEW

新建事务,如果当前存在事务,把当前事务挂起。

PROPAGATION_NOT_SUPPORTED

以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。

PROPAGATION_NEVER

以非事务方式执行,如果当前存在事务,则抛出异常。

PROPAGATION_NESTED

如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。

 
当使用PROPAGATION_NESTED时,底层的数据源必须基于JDBC 3.0,并且实现者需要支持保存点事务机制。
 
我们现在挨个来讲解下这个里面容易误解的几个:
 
1. PROPAGATION_REQUIRED
    假设有下面代码:
ServiceA {

    /**  

     * 事务属性配置为 PROPAGATION_REQUIRED  

     */  

    void methodA() {   

       try {

           ServiceB.methodB(); 

       } catch(Exception e){

          e.printstacktrace();

       }  

    }   

} 

ServiceB {

    /**  

     * 事务属性配置为 PROPAGATION_REQUIRED  

     */    

    void methodB() {   

    }   

}  
 
      其实required从我面试候选人来看,基本上都能答出来,但是看到上面的情景是回滚还是提交,基本上答上来的很少,我们再来看下定义,如果当前没有事务,就开启一个,如果有就加入到这个事务里面,也就是说整个是一个事务,所以B发生异常,会导致整个事务一块回滚。从这个里面可以看到,简单的将methodB异常捕获,认为整个事务会提交,其实是不行的。
 
     2. PROPAGATION_REQUIRES_NEW
    
ServiceA {

    /**  

     * 事务属性配置为 PROPAGATION_REQUIRED  

     */  

    void methodA() {   

       try {

           ServiceB.methodB(); 

       } catch(Exception e){

          e.printstacktrace();

       }  


    }   

} 

ServiceB {

    /**  

     * 事务属性配置为 PROPAGATION_REQUIRES_NEW  

     */    

    void methodB() {   

    }   

}  
      requires new这种类型,基本上所有的人都能答正确,A和B是两个独立的事务,内外两个事务没有任何影响,结果是B回滚,A提交
  
   3. PROPAGATION_REQUIRED
    
ServiceA {

    /**  

     * 事务属性配置为 PROPAGATION_REQUIRED  

     */  

    void methodA() {   

       try {

           ServiceB.methodB(); 

       } catch(Exception e){

          e.printstacktrace();

       }  

    }   

} 

ServiceB {

    /**  

     * 事务属性配置为 PROPAGATION_NESTED  

     */    

    void methodB() {   

    }   

}  
 
    从概念来看,有一个嵌套事务出现了
    我们来分析下这个,首先我们先根据一个图将这个分解下:
   
关于spring事务传播特性的相关问题的解释
            
    
    博客分类: spring spring 
    (上图A、B、C、D代表几个时机,我们用AD和BC代表这两个事务,1,2,3代表事务执行的三个阶段)
     嵌套事务达到的效果如下:
     1.  事务BC与事务AD一起commit,即:作为事务AD的子事务,事务BC只有在事务AD成功commit时(阶段3成功)才commit。这个需求简单称之为“联合成功”
     2.  事务BC的rollback不影响事务AD的commit
    也就是说第一个是required的特性,第二个是requires new的特性
 
     当BC事务成功commit时,PROPAGATION_NESTED的行为与PROPAGATION_REQUIRED一样。只有当事务AD在D点成功commit时,事务BC才真正commit,如果阶段3执行异常,导致事务AD rollback,事务BC也将一起rollback ,从而满足了“联合成功”
 
     当阶段2执行异常,导致BC事务rollback时,因为设置了savePoint,AD事务可以选择与BC一起rollback或继续阶段3的执行并保留阶段1的执行结果,从而满足了“隔离失败”。
 
      强调,补充一点:PROPAGATION_NESTED只是Spring针对JDBC3.0以上版本SavePoint机制的一个事务传播机制的扩展,J2EE体系中是没有的,所以如果应用中使用JTA作为底层的事务管理机制的话,使用Spring也是不可能支持PROPAGATION_NESTED。

 

 
  • 关于spring事务传播特性的相关问题的解释
            
    
    博客分类: spring spring 
  • 大小: 25.9 KB
相关标签: spring