事物回滚
有的时候方法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
本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
相关文章