Spring事务传播机制大白话(使用springboot,注解演示)

1. 我对传播机制的理解

  1. 为什么需要传播机制?
    因为事务之间可能存在相互调用,例如service业务层的方法存在相互调用,如果相互调用的方法都开启了事务(对应到springboot就是在方法上要添加@Transactional注解),那么程序需要以什么样的策略来执行事务呢?因此需要我们指定好事务传播机制,程序遇到这种情况就可以根据我们事先指定好的传播机制来执行。
    在这里插入图片描述

2. spring其中事务传播机制

默认的事务传播机制是required,点进注解看源码:
在这里插入图片描述

事务传播行为类型 说明
PROPAGATION_REQUIRED 如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。这是最常见的选择。
PROPAGATION_SUPPORTS 支持当前事务,如果当前没有事务,就以非事务方式执行
PROPAGATION_MANDATORY 使用当前的事务,如果当前没有事务,就抛出异常。
PROPAGATION_REQUIRES_NEW 新建事务,如果当前存在事务,把当前事务挂起。
PROPAGATION_NOT_SUPPORTED 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
PROPAGATION_NEVER 以非事务方式执行,如果当前存在事务,则抛出异常。
PROPAGATION_NESTED 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。

3. 实验验证

3.1. NEVER
3.1.1 调用方不开启事务(不添加Transactional注解)

代码如下,在controller调用service方法,实验前id=3的用户开始的money是1000,正常情况下想把其money更新为900
在这里插入图片描述
代码如下:
在这里插入图片描述
Controller中testTransaction去调用service中的testTransaction,可以看到右侧被调用的方法上边传播机制设置的NEVER,执行后效果如下:
在这里插入图片描述
在这里插入图片描述

发现当Controller层不加Transactional注解,Service层的testTransaction方法上添加Transactional并且把传播机制设置为NEVEL后,事务并没有生效,执行完后抛出了异常,但是数据库还是写进去了。

每次做完实验记得把数据库的900还原成1000;

3.1.2 调用方开启事务(添加Transactional注解)

在这里插入图片描述
请求执行后可以看到直接抛出了异常, Existing transaction found for transaction marked with propagation ‘never’,说明调用方式不能有事务的,如果有就直接抛出上图种的异常,并且Service层的业务代码并没有执行,没有抛出 除以0的异常。

3.1.3 总结

NEVEL传播机制,要求调用方不能有事务,在本测试中表现就是Ctroller中的testTransaction方法上不能有事务的注解

3.2. REQUIRED
3.2.1 service层的传播机制设置为required

service层的传播机制设置为required时,无论Controller层开启或者不开启事务,结果都是如下:
在这里插入图片描述
在这里插入图片描述

3.2.2 结论

说明当被调用方开启了事务,并且传播机制是required的时,一定会以事务的方式执行,具体表现就是如上边的图示,代码抛出了异常 / by zero,同时数据库中并没有写入900,说明异常后数据回滚了。

其他的就不再一一测试了,都是一个道理,始终记住列表中说的“当前事务”指的是调用方。

猜你喜欢

转载自blog.csdn.net/chen462488588/article/details/114526363