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

日常思考嵌套事务之spring的事务传播行为简述及举例

程序员文章站 2022-03-09 08:02:48
...

前段时间比较忙,一直没来得及记录问题。难得周末,静下心来。

前端时间搬砖的过程中,突然想到了一个问题,执行类A中调用a方法,a方法是在一个事务里,由于业务逻辑较为复杂,在a方法里又调用了类B的b方法,同时b方法也处于一个事务的中。这时候问题产生了:

1,如果,b方法实行失败,则b方法回滚,那a方法会回滚吗?

2,如果,a方法里调用b代码被try catch包住了,此时,b异常,回滚,同时这个异常被a吃了,a方法会回滚吗?

3,此事一定涉及了spring的事务传播行为,那如何去看spring定义哪种传播行为呢?如何spring的默认事务传播行为呢?

在想清楚这些问题之前,先查了一下事务传播行为的概念(《精通Srping4.x 企业应用开发实战》):

当我们调用一个基于Spring的Service接口方法时,它将运行于Spring管理的事务环境中,Service接口方法可能会在内部调用其他Service接口的方法以共同完成一完整的义务操作,因此就会产生服务接口方法嵌套调用的情况,Spring通过事务传播行为控制当前的事务如何传播到被签到调用的目标服务接口方法中,事务传播是Srping进行事务管理的重要概念。Spring在TranscationDefinition接口中规定了7中类型的事务传播行为,他们规定了事务方法和事务方法发生嵌套调用时事务如何进行传播,如下表:

事务传播行为类型
事务传播行为类型 说明
PROPAGATION_Required 如果当前没有事务,则新建一个事务;如果已经存在一个事务,则加入到这个事务中,这是最常见的选择
PROPAGATION_Supports

支持当前事务,如果当前没有事务,则以非事务方式运行

PROPAGATION_Mandatory 使用当前事务,如果当前没有事务,则抛出异常
PROPAGATION_Requires_new 新建事务,如果当前存在事务,则把当前事务挂起
PROPAGATION_Not_Supported 以非事务的方式执行操作,如果当前存在事务,则把当前事务挂起
PROPAGATION_Never 以非事务方式执行,如果当前存在事务,则抛出异常
PROPAGATION_Nested 如果当前存在事务,则在嵌套事务内执行;如果当前没有事务,则执行与PROPAGATION——Required类似的操作

 

备注:在使用PROPAGATION_Nested时,底层的数据源必须基于JDBC3.0,并且实现者要支持保存点事务机制。

ok,概念就是这些,现在,我们去代码里看一眼

先看下TransactionDefinition,就像上文介绍的一样,传播行为分了0-6,七种。

日常思考嵌套事务之spring的事务传播行为简述及举例

再看getPropagationBehavior方法的实现DefaultTransactionDefinition里的代码

日常思考嵌套事务之spring的事务传播行为简述及举例

再找到this.propagationBehavior

日常思考嵌套事务之spring的事务传播行为简述及举例

就是第一种

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

至此,已经知道了spring的事务传播行为的概念和默认级别

先看问题1,两个方法在一个事务里,那b抛出异常,回滚,a肯定是回滚的。

经测试,问题2,a也会抛出异常,并且都没有保存成功,Transaction rolled back because it has been marked as rollback-only。为啥呢?因为spring默认的是PROPAGATION_Required,执行b方法的时候,b的事务和a的事务是同一个事务,b抛异常回滚了,虽然把异常捕获了,但是a执行需要事务,此时事务已经回滚掉了,所以无法执行下去了。如果改变事务的传播行为的级别为PROPAGATION_Requires_new 或者 PROPAGATION_Nested,a和b用了两个事务或嵌套事务,就可以解决问题,此时a保存成功,b回滚。

问题2中已经涉及了如何修改spring的事务级别,那怎么设置呢?答案是在@Transactional注解上

在嵌套方法,也就是b方法上添加

@Transactional(propagation = Propagation.REQUIRES_NEW)

即可。

现在,再看一下@Transactional注解可以设置哪些属性

日常思考嵌套事务之spring的事务传播行为简述及举例

1,事务隔离级别

2和3,遇到哪些exception不回滚

4,事务传播行为

5,是否只读

6和7,遇到哪些exception回滚

8,超时时间

9,指定transactionManager

10,跟9相同

 

至此,所有的问题就都解释清楚了。

昨天领导说,公司提供的技术平台,目的是为了简化大家的开发流程,提高开发效率。但是你的其他方面的能力,在随着你使用公司技术平台的能力的增强而减弱,这点一定要值得警惕。说的很有道理。知其然,知其所以然,方能在出现问题的时候,及时排查。

 

相关标签: spring