传播行为介绍
事务的传播行为指的是一个事务方法被另外一个事务方法调用时,这个事务该怎么进行。
如:事务方法B被事务方法A调用时,B事务是该融入A事务,还是重新创建一个事务,这是由事务B的传播行为决定的。
事务的传播方式
public void methodA() {
// A do something
methodB();
// A do something
}
public void methodB() {
// B do something
}
设定:A 和 B 都开启事务,A称为外部事务,B称为内部事务。
以mysql为例,上述代码相当于
最外层时A事务,内部时B事务,虽然mysql不支持这个写,但可以这样理解传播行为。
(一)融入事务
根据上面的图,融入事务就是B事务融入外部事务,就相当于没有了 内部的 begin commit;
如下所示:所以A 和 B 任意一个方法出线异常的时候事务都会回滚。
(二)挂起事务
挂起事务可以理解为A事务和B事务执行相互不影响,就图所示:B执行过程中出线异常回滚,不会影响A事务,而B执行完成后提交事务,A在执行出异常,B也不再会回滚事务。
这样的实现方式主要通过切换数据库连接实现的,在执行A事务过程中,执行到B事务就是将A事务信息保存,同时切换数据库连接,然后执行B事务,在B事务执行完成后,在根据保存信息切换回来,从而实现A和B事务会不影响。
在Java中主要通过ThreadLocal实现的。
(三)嵌套事务
嵌套事务主要像下面这样,保存a这个时刻的快照信息,当出现问题就会回滚到a
Spring的七大传播行为
基于以上的融入事务,挂起事务和嵌套事务我们就可以来理解spring中的七大传播行为。
REQUIRED
required表示这个方法必须要有事务,可以理解为外部有事务就融入外部事务,外部没有事务就创建一个事务。
SUPPORTS
supports可以理解为支持事务,如果外部有事务就融入外部事务,如果外部没有事务就以非事务方式运行。
MANDATORY
mandatory可以理解为外部必须有事务,如果没事务就抛出异常。
REQUIRES_NEW
requires_new 可以理解为必须运行在自己的事务中,如果外部有事务就将外部事务挂起。
NOT_SUPPORTED
not_supported可以理解为不使用事务,外部有事务就将外部事务挂起。
NEVER
never可以理解为不支持事务,如果外部有事务就抛异常
NESTED
nested可以理解为当前事务会嵌套在外部事务执行。
总结
理解七大传播行为得理解融入事务,挂起事务和嵌套事务这三种方式,这理解了七大传播行为就比较好理解。
推荐视频:一个视频教会你spring的事务传播行为_哔哩哔哩_bilibili
事务行为 | 说明 |
---|---|
PROPAGATION_REQUIRED | 支持当前事务,假设当前没有事务。就新建一个事务 |
PROPAGATION_SUPPORTS | 支持当前事务,假设当前没有事务,就以非事务方式运行 |
PROPAGATION_MANDATORY | 支持当前事务,假设当前没有事务,就抛出异常 |
PROPAGATION_REQUIRES_NEW | 新建事务,假设当前存在事务。把当前事务挂起 |
PROPAGATION_NOT_SUPPORTED | 以非事务方式运行操作。假设当前存在事务,就把当前事务挂起 |
PROPAGATION_NEVER | 以非事务方式运行,假设当前存在事务,则抛出异常 |
PROPAGATION_NESTED | 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。 |