【spring核心】Spring的事务传播机制

事务传播机制


REQUIRED(Spring默认的事务传播类型 required:需要、依赖、依靠):如果当前没有事务,则自己新建一个事务,如果当前存在事务则加入这个事务
当A调用B的时候:如果A中没有事务,B中有事务,那么B会新建一个事务;如果A中也有事务、B中也有事务,那么B会加入到A中去,变成一个事务,这时,要么都成功,要么都失败。(假如A中有2个SQL,B中有两个SQL,那么这四个SQL会变成一个SQL,要么都成功,要么都失败)

SUPPORTS(supports:支持;拥护):当前存在事务,则加入当前事务,如果当前没有事务,就以非事务方法执行
如果A中有事务,则B方法的事务加入A事务中,成为一个事务(一起成功,一起失败),如果A中没有事务,那么B就以非事务方式运行(执行完直接提交);

MANDATORY(mandatory:强制性的):当前存在事务,则加入当前事务,如果当前事务不存在,则抛出异常。
如果A中有事务,则B方法的事务加入A事务中,成为一个事务(一起成功,一起失败);如果A中没有事务,B中有事务,那么B就直接抛异常了,意思是B必须要支持回滚的事务中运行

REQUIRES_NEW(requires_new:需要新建):创建一个新事务,如果存在当前事务,则挂起该事务。
B会新建一个事务,A和B事务互不干扰,他们出现问题回滚的时候,也都只回滚自己的事务;

NOT_SUPPORTED(not supported:不支持):以非事务方式执行,如果当前存在事务,则挂起当前事务
被调用者B会以非事务方式运行(直接提交),如果当前有事务,也就是A中有事务,A会被挂起(不执行,等待B执行完,返回);A和B出现异常需要回滚,互不影响

NEVER(never:从不): 如果当前没有事务存在,就以非事务方式执行;如果有,就抛出异常。就是B从不以事务方式运行
A中不能有事务,如果没有,B就以非事务方式执行,如果A存在事务,那么直接抛异常

NESTED(nested:嵌套的)嵌套事务:如果当前事务存在,则在嵌套事务中执行,否则REQUIRED的操作一样(开启一个事务)
如果A中没有事务,那么B创建一个事务执行,如果A中也有事务,那么B会会把事务嵌套在里面。


光看这么这些字儿新手会懵逼 没关系 我们一个一个慢慢讲:

@Service
public class ServiceAAA {

    @Autowired
    private ServiceBBB serviceBBB;
    
    @transaction
    public void helloA() {
        System.out.println("****业务逻辑1****");
        serviceBBB.helloB();
        System.out.println("****业务逻辑2****");
    }
}

看这段代码 服务A 里面 方法helloA去调服务B的方法 然后前后还有A方法的一些业务逻辑。假设 我们给这两个方法都加上了:
@transaction
这时候就是事务里面调用事务。

那么这样执行在mysql中会是什么样呢:

BEGIN:
 *****A*****
  BEGIN:
  ****B****
  COMMIT;
 *****A****
COMMIT;  

很遗憾这种嵌套的写法 在mysql里面是不允许的。 这种去mysql执行的时候。

到了第二个BEGIN, 第一个begin就强行结束了。 它不允许事务里面还有事务。

那么spring帮我们做了哪些事呢? 它直接把这俩合二为一 意味着要死大家一起死

BEGIN:
 *****A*****

  ****B****

 *****A****
COMMIT;  

像这样,两个事务就合并成了一个事务。
这个就叫做事务的融入

下一个
我就是想这两个事务各自独立 互不影响 A回滚了 不影响B B回滚了不影响A.
这个时候 这种情况 spring 或者 mybatis框架怎么解决呢?

BEGIN:
 *****A*****
  BEGIN:
  ****B****
  COMMIT;
 *****A****
COMMIT;  

这里要讲一个事务的挂起
什么叫挂起 就是我们从连接池里面拿一个连接去执行A事务,执行到A里面的B事务的时候 将这个线程挂起, 从连接池里面再拿一个连接 去执行B事务,等B事务执行完之后 再触发第一个连接去执行A事务。

好理解把。

然后再说一个事务的嵌套

BEGIN:
 *****A*****
  BEGIN:
  ****B****
  COMMIT;
 *****A****
COMMIT;  

刚才不是说这样mysql不能执行吗?是的 所以大神们搞了一个天才的设计就是手动回滚

BEGIN:
 *****A*****
  保存点a
  ****B****
  回到保存点a
 *****A****
COMMIT;  

我不用你mysql的回滚机制 我自己搞一个回滚 这个就实现了嵌套。


搞清楚了这三个,上面几个主要的传播机制就好理解了比如:

REQUIRED(Spring默认的事务传播类型 required:需要、依赖、依靠):如果当前没有事务,则自己新建一个事务,如果当前存在事务则加入这个事务
当A调用B的时候:如果A中没有事务,B中有事务,那么B会新建一个事务;如果A中也有事务、B中也有事务,那么B会加入到A中去,变成一个事务,这时,要么都成功,要么都失败。(假如A中有2个SQL,B中有两个SQL,那么这四个SQL会变成一个SQL,要么都成功,要么都失败)

B有事务 但是被一个没有事务的A方法调用 它就自己建一个事务。
如果A B都有那就是上面说的事务的融入 合成一个事务。

SUPPORTS(supports:支持;拥护):当前存在事务,则加入当前事务,如果当前没有事务,就以非事务方法执行
如果A中有事务,则B方法的事务加入A事务中,成为一个事务(一起成功,一起失败),如果A中没有事务,那么B就以非事务方式运行(执行完直接提交);

如果A B都有事务 还是融入 和上面没区别。
关键是如果B有 调用它的A没有, 那么就听大哥的 B的事务作废

MANDATORY(mandatory:强制性的):当前存在事务,则加入当前事务,如果当前事务不存在,则抛出异常。
如果A中有事务,则B方法的事务加入A事务中,成为一个事务(一起成功,一起失败);如果A中没有事务,B中有事务,那么B就直接抛异常了,意思是B必须要支持回滚的事务中运行

还是
如果A B都有事务 还是融入 和上面没区别。
关键是如果B有 调用它的A没有, 那么B不能听大哥的 直接抛异常
告诉调用者 你用一个没有事务注解的方法调用老子 这是不行的

REQUIRES_NEW(requires_new:需要新建):创建一个新事务,如果存在当前事务,则挂起该事务。
B会新建一个事务,A和B事务互不干扰,他们出现问题回滚的时候,也都只回滚自己的事务;

如果A B 都有事务 那么B事务不能和A融入 这时候A事务和B事务各自独立 互补影响

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值