事物回滚

2022-06-21 00:00:00 事物

有的时候方法A()里面包含方法B(),C()

Transactional(rollbackFor = Exception.class)
public void A(){
 B();
 c();
}

@Transactional(rollbackFor = Exception.class)
public void B(){

}

@Transactional(rollbackFor = Exception.class)
public void C(){

}

 

 

这个时候当B方法内部有异常的时候,即使你在B方法内部捕获到了,方法A中对数据库做的操作还是会回滚的,这个是以为方法B有异常了,把整个事物设置为readonly了,在commit的时候就会报错

《事物回滚》

 

那么怎么能让方法B内部回滚,方法A不回滚的,现实中也是有这样的业务存在的,比如:工作流审批,我审批通过了,要下传下游接口,这个时候接口报错了,不能以为接口报错整个工作流都要回滚,这个明显是不符合业务逻辑的。 那么有没有方法解决呢。

这个就要区分了:

1.在方法B()上加下面的注解

@Transactional(rollbackFor = Exception.class,propagation =Propagation.REQUIRES_NEW)

从字面即可知道,new,每次都要一个新事务,该传播级别的特点是,每次都会新建一个事务,并且同时将上下文中的事务挂起,执行当前新建事务完成以后,上下文事务恢复再执行。

也就是说我在执行B方法的时候是新开了一个事物,即使方法B中有异常回滚,A方法也不会回滚。这个比较适合比较独立的业务逻辑。但是如果我在方法A中执行了一个插入操作,由于事物还没有提交,当我进入方法B时,是新开了一个事物,这个我们想查到A中插入的数据是查不到的。

2.在方法B()上加下面的注解

@Transactional(rollbackFor = Exception.class,propagation = Propagation.NESTED)

Propagation.NESTED解释:

字面也可知道,nested,嵌套级别事务。该传播级别特征是,如果上下文中存在事务,则嵌套事务执行,如果不存在事务,则新建事务。

那么什么是嵌套事务呢?很多人都不理解,我看过一些博客,都是有些理解偏差。

嵌套是子事务套在父事务中执行,子事务是父事务的一部分,在进入子事务之前,父事务建立一个回滚点,叫save point,然后执行子事务,这个子事务的执行也算是父事务的一部分,然后子事务执行结束,父事务继续执行。重点就在于那个save point。看几个问题就明了了:

如果子事务回滚,会发生什么?

父事务会回滚到进入子事务前建立的save point,然后尝试其他的事务或者其他的业务逻辑,父事务之前的操作不会受到影响,更不会自动回滚。

如果父事务回滚,会发生什么?

父事务回滚,子事务也会跟着回滚!为什么呢,因为父事务结束之前,子事务是不会提交的,我们说子事务是父事务的一部分,正是这个道理。那么:

事务的提交,是什么情况?

是父事务先提交,然后子事务提交,还是子事务先提交,父事务再提交?答案是第二种情况,还是那句话,子事务是父事务的一部分,由父事务统一提交。

也就是说:

我在方法B中的事物就相当于是方法A的的一个子事物,A是B是父级事物,当方法B异常回滚到方法A没有执行B之前,然后执行下面的方法C,这个是传播方式的好处是,子事物可以共享父事物里面的东西,比如我在父事物中执行一个插入操作,那么在子事物可以查到这个插入的数据。

参考地址:https://www.cnblogs.com/wj0816/p/8474743.html

    原文作者:应小勇
    原文地址: https://blog.csdn.net/qq_26834541/article/details/82461569
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。

相关文章