文章插图
如果 方法B 抛出异常后,方法A 使用 try-catch 处理了方法B的异常(如下代码),并没有向外抛出,此时事务又如何处理的 ?

文章插图
方法A也会回滚 。
从事务的特性我们可知,事务具有原子性 。方法A和方法B同属一个事务,当方法B抛出异常,触发回滚操作后,整个事务的操作都会回滚 。
因此,Spring 在处理事务过程中 , 当事务的传播性设置为REQUIRED,在整个事务的调用链上,任何一个环节抛出的异常都会导致全局回滚 。
3.2 REQUIRES_ NEW每次都开启一 个新的事务 。

文章插图
例子:

文章插图
上面例子中,方法B的传播性设置为 REQUIRES_NEW,方法A仍然是REQUIRED,当A调用B时,具体调用链路如下:

文章插图
具体执行过程:
- 方法A被执行前,如果调用者没有开启事务,方法A开启一个事务1,然后执行insert,此时没有提交;
- 方法B的事务传播性设置为REQUIRES_NEW,当被方法A调用时,此时方法A的事务1会被挂起,方法B开启自己的事务2,然后执行insert,此时并没有提交;
- 当方法B执行完毕后 , 提交事务2;
- 恢复事务1 , 最终提交 。
方法B的insert操作会被回滚掉,方法A不受影响 。但这里有个前提,方法A需要try-catch方法B的异常,使其异常不会往上传递,从而导致方法A接收到异常,导致回滚 。

文章插图
3.3 SUPPORTED当外层方法A存在事务,方法B加入到当前事务中,以事务的方式执行 。

文章插图
当外层方法A不存在事务,方法B不会创建新的事务 , 以非事务的方式执行 。

文章插图
例子1:

文章插图

文章插图
以上例子,方法A没有加事务注解,方法B的加了事务注解,并且传播为SUPPORTS 。
具体执行过程:
- 方法A以非事务的方式执行insert操作 。
- 方法B被调用,由于其外层事务A没有开启事务,方法B也是以非事务方法执行insert操作 。

文章插图
例子2:

文章插图
以上例子,方法A和B都加上了事务注解,其中方法A的传播性为REQUIRED,方法B的传播性为SUPPORTS 。
具体执行过程:
- 如果方法A的调用方没有开启事务,则方法A开启事务,并执行insert操作,但没有提交;
- 方法B被调用 , 由于其外层方法A开启了事务,因此方法B加入到方法A开启的事务中,并执行insert,但没有提交;
- 当事务中的所有操作执行成功后,事务提交 。

文章插图
3.4 NOT_SUPPORTED不支持事务 。
如果外层方法存在事务,则挂起外层事务,以非事务方式执行 , 执行完毕后 , 恢复外层事务 。

文章插图
例子:

文章插图
以上例子:方法A和B都加上了事务注解 , 方法A的传播性为REQUIRED,方法B为NOT_SUPPORTED 。
具体执行过程:
- 如A的调用方没有开启事务 , 方法A开启事务,并执行insert,但没有提交 。
- 方法A调用方法B时,方法B的传播性为NOT_SUPPORTED,不支持事务,然后挂起外层方法A的事务,方法B以非事务的方式执行insert 。
推荐阅读
- 炒面筋的家常做法,油面筋最好吃的七种家常做法
- 简易版的SpringBoot是如何实现的!!!
- Spring非常实用的技巧,你确定知道?
- 分布式场景下的事务机制
- SpringBoot中如何优雅地个性化定制Jackson
- 监控 Spring Cloud 微服务的实践方案
- 解析MongoDB的并发控制和事务隔离级别:保证数据一致性
- SpringBoot+虚拟线程,接口吞吐量成倍增加,太爽了!
- springboot-如何集成Validation进行参数校验
- Spring6提供的四种远程接口调用神器!你知道那种?
