事务457——事务的七个传播行为

继上一篇文章,我们讲到了事务的传播行为,具体是那七个。我们在罗列一遍:

PROPAGATION_REQUIRED

如果存在一个事务,则支持当前事务。如果没有事务则开启一个新的事务。
PROPAGATION_SUPPORTS

如果存在一个事务,支持当前事务。如果没有事务,则非事务的执行。但是对于事务同步的事务管理器,PROPAGATION_SUPPORTS与不使用事务有少许不同。
PROPAGATION_MANDATORY

如果已经存在一个事务,支持当前事务。如果没有一个活动的事务,则抛出异常。
PROPAGATION_REQUIRES_NEW

总是开启一个新的事务。如果一个事务已经存在,则将这个存在的事务挂起。
PROPAGATION_NOT_SUPPORTED

总是非事务地执行,并挂起任何存在的事务
PROPAGATION_NEVER

总是非事务地执行,如果存在一个活动事务,则抛出异常

PROPAGATION_NESTED

如果一个活动的事务存在,则运行在一个嵌套的事务中. 如果没有活动事务, 则按TransactionDefinition.PROPAGATION_REQUIRED 属性执行
我们就转账例子说一下。 比如,在转账的services中有个两个方法,方法A和方法B。

方法A
 ServiceA { 
        read A =100  ;   
        If(doSome()){
                               A = A + 1;  
                           }else{
                               A = A - 1;  
                          }
        Update A;
        Commit;       
          }   
1
2
3
4
5
6
7
8
9
10
方法B
ServiceB {                 
         void doOther() {
                 read B ;
                 B = B – 1;
                Update B;
                  If(B>0){
                Commit;
                Return ture;
                  }else{
                     Rollback;
                Return false;
                  }
       }
1
2
3
4
5
6
7
8
9
10
11
12
13
(1)REQUIRED——必须有事务
指定的方法必须在事务内执行。若当前存在事务,就加入到当前事务中;若当前没有事务,则创建一个新事务。这种传播行为是最常见的选择,也是Spring默认的事务传播行为。

比如说,Servicedo的doOther()方法上加上了传播行为PROPAGATION_REQUIRED。若doSome()方法在调用doOther()方法时就是在事务内运行的,则doOther()方法的执行也加入到该事务内执行。若doSome()方法在调用doOther()方法时没有在事务内执行,则doOther()方法会促使doSome()创建一个事务,并在加入其中执行。在doSome()或者在doOther()内的任何地方出现异常,事务都会被回滚。即使doOther()的事务已经被提交,doSome()在接下来fail要回滚,doOther()也要回滚。

简单来说,谁调加了REQUIRED的方法,谁就要具有一个事务,被调用的方法可有可无事务,但是调他的必须有事务 


(2)SUPPORTS ——支持事务
指定的方法支持当前事务,但若当前没有事务,也可以以非事务方式执行。 定义在再方法doOther()上,定义在doSome()上。

(3)MANDATORY ——托管事务
指定的方法必须在当前事务内执行。就是说,他只能被一个父事务调用。若当前没有事务,则直接抛出异常。 定义在再方法doOther()上,定义在doSome()上。doSome()是father。

(4)REQUIRES_NEW ——需要新事务
总是新建一个事务,若当前存在事务,就将当前事务挂起,直到新事务执行完毕。

比如,我们设计ServiceA.doSome()的事务级别为PROPAGATION_REQUIRED,ServiceB.doOther()的事务级别为PROPAGATION_REQUIRES_NEW,那么当执行到ServiceB.doOther()的时候,ServiceA.doSome()所在的事务就会挂起,ServiceB.doOther()会起一个新的事务,等待ServiceB.doOther()的事务完成以后,他才继续执行。

优先级别:PROPAGATION_REQUIRES_NEW >PROPAGATION_REQUIRES

PROPAGATION_REQUIRED与PROPAGATION_REQUIRED 的事务区别:在于事务的回滚程度。因为ServiceB.doOther()是新起一个事务,那么就是存在两个不同的事务。如果ServiceB.doOther()已经提交,那么ServiceA.doSome()失败回滚,ServiceB.doOther()是不会回滚的。如果ServiceB.doOther()失败回滚,如果他抛出的异常被ServiceA.doSome()捕获,ServiceA.doSome()事务仍然可能提交。

(5)NOT_SUPPORTED ——不支持事务
指定的方法不能在事务环境中执行,若当前存在事务,就将当前事务挂起。 
比如ServiceA.doSome()的事务级别是PROPAGATION_REQUIRED ,而ServiceB.doOther()的事务级别是PROPAGATION_NOT_SUPPORTED ,那么当执行到ServiceB.doOther()时,ServiceA.doSome()的事务挂起,而他以非事务的状态运行完,再继续ServiceA.doSome()的事务。一般,在非常耗时查询的时候就可以使用Not Support,挂起这个查询方法,让其他方法先行,避免事务时间超长。

优先级别:PROPAGATION_NOT_SUPPORTED>PROPAGATION_REQUIRED

(6)NEVER ——禁用事务
指定的方法不能在事务环境下执行,若当前存在事务,就直接抛出异常。 
假设ServiceA.doSome()的事务级别是PROPAGATION_REQUIRED,而ServiceB.doOther()的事务级别是PROPAGATION_NEVER ,那么ServiceB.doOther()就要抛出异常了。 
简而言之:事务掉了拥有NEVER属性的方法统统要出错。 
优先级别:PROPAGATION_NEVER>PROPAGATION_REQUIRED

(7)NESTED ——嵌套事务
指定的方法必须在事务内执行。若当前存在事务,则在嵌套事务内执行;若当前没有事务,则创建一个新事务。并且使用savepoint设置事务的回滚点。 


那怎么使用savapoint()的,看下面这个例子

savapoint()使用
ServiceA {        
     void doSome() {   
         try {
      //savepoint   
             ServiceB.doOther();    //PROPAGATION_NESTED 级别
         } catch (SomeException) {   
             // 执行其他业务, 如 ServiceC.doElse()等等
         }   
     }   
  }   
1
2
3
4
5
6
7
8
9
10
加入,ServiceB.doOther()失败回滚,那么ServiceA.doSome() 也会回滚到savepoint点上,ServiceA.doSome() 可以选择另外一个分支,比如ServiceC.doElse(),继续执行,来尝试完成自己的事务。

PROPAGATION_Nested与PROPAGATION_REQUIRES_NEW的区别是:PROPAGATION_REQUIRES_NEW另起一个事务,将会与他的父事务相互独立,而Nested的事务和他的父事务是相依的,他的提交是要等和他的父事务一块提交的。也就是说,如果父事务最后回滚,他也要回滚的。
--------------------- 
作者:童小绿 
from:https://blog.csdn.net/tsj11514oo/article/details/52389124?utm_source=copy 
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值