JAVA面试题分享一百三十二:Spring的事务传播机制?

一、前言

Spring在TransactionDefinition接口中规定了7种类型的事务传播行为。事务传播行为是Spring框架独有的事务增强特性,他不属于的事务实际提供方数据库行为。这是Spring为我们提供的强大的工具箱,使用事务传播行可以为我们的开发工作提供许多便利。但是人们对他的误解也颇多,你一定也听过“service方法事务最好不要嵌套”的传言。要想正确的使用工具首先需要了解工具。本文对七种事务传播行为做详细介绍,内容主要代码示例的方式呈现。

二、为什么会有传播机制

spring 对事务的控制,是使用 aop 切面实现的,我们不用关心事务的开始,提交 ,回滚,只需要在方法上加 @Transactional 注解,这时候就有问题了。

  • 场景一: serviceA 方法调用了 serviceB 方法,但两个方法都有事务,这个时候如果 serviceB 方法异常,是让 serviceB 方法提交,还是两个一起回滚。
  • 场景二:serviceA 方法调用了 serviceB 方法,但是只有 serviceA 方法加了事务,是否把 serviceB 也加入 serviceA 的事务,如果 serviceB 异常,是否回滚 serviceA 。
  • 场景三:serviceA 方法调用了 serviceB 方法,两者都有事务,serviceB 已经正常执行完,但 serviceA 异常,是否需要回滚 serviceB 的数据。

三、Spring 事务传播机制有哪些?

Spring 事务传播机制可使用 @Transactional(propagation=Propagation.REQUIRED) 来定义,Spring 事务传播机制的级别包含以下 7 种:

  1. Propagation.REQUIRED:默认的事务传播级别,它表示如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。
  2. Propagation.SUPPORTS:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。
  3. Propagation.MANDATORY:(mandatory:强制性)如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。
  4. Propagation.REQUIRES_NEW:表示创建一个新的事务,如果当前存在事务,则把当前事务挂起。也就是说不管外部方法是否开启事务,Propagation.REQUIRES_NEW 修饰的内部方法会新开启自己的事务,且开启的事务相互独立,互不干扰。
  5. Propagation.NOT_SUPPORTED:以非事务方式运行,如果当前存在事务,则把当前事务挂起。
  6. Propagation.NEVER:以非事务方式运行,如果当前存在事务,则抛出异常。
  7. Propagation.NESTED:如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于 PROPAGATION_REQUIRED。

以上 7 种传播机制,可根据“是否支持当前事务”的维度分为以下 3 类:
 

image.png


看到这里,有人可能会说:说了这么多,我也看不懂啊,即使看懂了,我也记不住啊?这要咋整?

没关系,接下来我们用一个例子,来说明这 3 类事务传播机制的区别。

以情侣之间是否要买房为例,我们将以上 3 类事务传播机制可以看作是恋爱中的 3 类女生类型:

  • 普通型
  • 强势型
  • 懂事型

这三类女生如下图所示:
 

image.png


支持当前事务的“女生”,这里的事务指的是“房子”,它分为 3 种(普通型女生):

  • Propagation.REQUIRED(需要有房子):有房子了咱们一起住,没房子了咱们一起赚钱买房子。
  • Propagation.SUPPORTS(可以有房子):有房子了就一起住,没房子了咱们就一起租房子。
  • Propagation.MANDATORY(强制有房子):有房子了就一起住,没房子了就分手。

不支持当前事务的“女生”也分为 3 种(强势型或者叫事业型):

  • Propagation.REQUIRES_NEW:不要你的房子,必须一起赚钱买房子。
  • Propagation.NOT_SUPPORTED:不要你的房子,必须一起租房子。
  • Propagation.NEVER:必须一起租房子,你有房子就分手。

最后一种是嵌套性事务 Propagation.NESTED,它属于懂事型女友,如果有房子了就以房子为基础做点小生意,卖个花生、水果啥的,如果买卖成了,那就继续发展;如果失败了,至少还有房子;如果没房子也没关系,一起赚钱买房子。

四、支持当前事务(在同一个事务中)

  • PROPAGATION_REQUIRED:支持当前事务,如果不存在,就新建一个事务。
  • PROPAGATION_MANDATORY:支持当前事务,如果不存在,就抛出异常。
  • PROPAGATION_SUPPORTS:支持当前事务,如果不存在,就不使用事务。

五、不支持当前事务(不在同一个事务中)

  • PROPAGATION_NEVER:以非事务的方式运行,如果有事务,则抛出异常。
  • PROPAGATION_NOT_SUPPORTED:以非事务的方式运行,如果有事务,则挂起当前事务。
  • PROPAGATION_REQUIRES_NEW:新建事务,如果有事务,挂起当前事务(两个事务相互独立,父事务回滚不影响子事务)。
  • PROPAGATION_NESTED:如果当前事务存在,则嵌套事务执行(指必须依存父事务,子事务不能单独提交且父事务回滚则子事务也必须回滚,而子事务若回滚,父事务可以回滚也可以捕获异常)。如果当前没有事务,则进行与PROPAGATION_REQUIRED类似的操作。

实际上我们主要用的是PROPAGATION_REQUIRED默认属性,一些特殊业务下可能会用到PROPAGATION_REQUIRES_NEW以及PROPAGATION_NESTED。下面我会假设一个场景,并主要分析这三个属性。

  • 28
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

之乎者也·

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值