springboot中事务回滚,调用链中存在多个@Transactional的事务回滚

SpringBoot事务使用和回滚

Springboot中事务的使用:

  1. 启动类加上@EnableTransactionManagement注解,开启事务支持(其实默认是开启的)。

  2. 在使用事务的public(只有public支持事务)方法(或者类-相当于该类的所有public方法都使用)加上@Transactional注解。

在实际使用中一般是在service中使用@Transactional,那么对于controller->service流程中:

如果controller未开启事务,service中开始了事务,service成功执行,controller在之后的运行中出现异常(错误),不会自动回滚。

也就是说,只有在开启事务的方法中出现异常(默认只有非检测性异常才生效-RuntimeException )(错误-Error)才会自动回滚。

如果想要对抛出的任何异常都进行自动回滚(而不是只针对RuntimeException),只需要在使用@Transactional(rollbackFor = Exception.class)即可。

开启事务的方法中事务回滚的情况:

①未发现的异常,程序运行过程中自动抛出RuntimeException或者其子类,程序终止,自动回滚。

②使用TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();进行手动回滚。

③注意:如果在try-catch语句中对可能出现的异常(RuntimeException)进行了处理,没有再手动throw异常,spring认为该方法成功执行,不会进行回滚,此时需要调用②中方法进行手动回滚,如下图:

另外,如果try-catch语句在finally中进行了return操作,那么catch中手动抛出的异常也会被覆盖,同样不会自动回滚。

在这里插入代码片

//不会自动回滚

try{
   throw new RuntimeException();
}catch(RuntimeException e){
   e.printStackTrace();
}finally{
}

//会自动回滚

try{
   throw new RuntimeException();
}catch(RuntimeException e){
   e.printStackTrace();
   throw new RuntimeException();
}finally{
}

springboot调用链中存在多个@Transactional的事务回滚

在Spring Boot中,@Transactional注解是用来定义事务边界的主要手段。它可以应用于类或者方法级别,以声明性地控制事务。当在调用链中存在多个@Transactional注解时,Spring的事务传播行为将决定这些事务是如何相互作用的。下面我将一步一步解释这个过程。

1. @Transactional注解基础

@Transactional注解告诉Spring,被注解的方法或类中的所有方法应该运行在一个事务上下文中。如果该方法或类中的操作失败,则事务可以被回滚,即取消所有操作,以保持数据的一致性。

如果@Transactional中没有配置自定义回滚规则,则事务将在RuntimeException和Error上回滚,但不会在检查异常上回滚。

2. 事务传播行为(Propagation Behavior)

在调用链中,当一个@Transactional方法调用另一个@Transactional方法时,事务是如何管理的?答案在于事务的传播行为。Spring定义了几种传播行为:

  • REQUIRED(默认):如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。
  • REQUIRES_NEW:总是创建一个新的事务,并暂停当前的事务(如果存在)。
  • SUPPORTS:如果当前存在事务,则加入该事务;如果没有,则以非事务方式执行。
  • NOT_SUPPORTED:总是以非事务方式执行,并暂停当前的事务(如果存在)。
  • MANDATORY:如果当前存在事务,则加入该事务;如果没有,则抛出异常。
  • NEVER:总是以非事务方式执行,如果当前存在事务,则抛出异常。
  • NESTED:如果当前存在事务,则在嵌套事务内执行;如果没有,则表现如REQUIRED

3. 事务回滚

当在@Transactional注解的方法中发生异常时,事务默认将回滚。Spring框架默认对运行时异常(RuntimeException)和错误(Error)触发回滚,而对检查型异常(Exception的直接子类,除了RuntimeException)不回滚,除非明确指定。

4. 调用链中的事务回滚

  • 同一事务内的回滚:如果所有方法都在同一个事务上下文中(例如,都使用REQUIRED传播行为,且第一个方法启动了事务),那么任何方法中的失败都会导致整个事务回滚。
  • 独立事务的回滚:如果某个方法配置为REQUIRES_NEW,它将在自己的事务中运行。如果这个独立事务失败了,它会回滚,但不会影响其他事务的执行或回滚。
  • 嵌套事务的回滚:使用NESTED传播行为时,外部事务可以成功提交,而嵌套事务失败时只回滚嵌套事务的更改。

独立事务和嵌套事务

独立事务(REQUIRES_NEW

回滚特性

  • 当方法B以REQUIRES_NEW传播行为被调用时,无论外部事务A的状态如何,B都会启动一个新的事务。
  • 如果B事务失败,仅B事务会回滚。这个回滚操作不会影响到事务A的状态;A可以独立于B继续执行,并根据自己的逻辑成功提交或回滚。
  • B的回滚仅限于B事务内的操作。即使B失败并回滚,A事务可以无视B的失败,根据自己的业务逻辑决定是否成功提交。
  • 独立事务(REQUIRES_NEW),如果B成功了(即B事务已经提交),然后A失败了,B是不会回滚的。这是因为B事务已经独立于A事务成功提交,其操作结果已经被永久保存。

使用场景

  • 当你需要保证某个业务操作完全独立于当前的事务环境时,例如,记录日志、发送通知等操作,这些操作即使失败也不应该影响主业务流程的执行。
嵌套事务(NESTED

回滚特性

  • 嵌套事务依赖于外部事务A的存在。当B以NESTED传播行为被调用时,它在A中创建一个保存点,作为嵌套事务执行。
  • 如果B事务失败,它会回滚到B开始执行时的保存点,这个回滚只会撤销B事务内的更改,不影响A事务中B之外的操作。
  • 如果外部事务A决定回滚,那么包括B在内的所有更改都会被撤销,即整个嵌套事务会被回滚。

使用场景

  • 当你的业务逻辑中包含了一系列的步骤,这些步骤需要作为整体被成功提交,但是在这个过程中某些步骤可能需要单独地进行回滚和重试时。嵌套事务允许这种细粒度的控制。
核心区别
  • 事务依赖性独立事务与外部事务完全独立,而嵌套事务依赖于外部事务。
  • 回滚点:独立事务的回滚不影响其他事务,嵌套事务的回滚则是回到其在外部事务中的保存点,但不影响外部事务的其他部分。
  • 使用场景:独立事务适用于需要完全隔离的操作,嵌套事务适用于需要事务内部细粒度控制的场景。
  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

洪泽涛

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

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

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

打赏作者

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

抵扣说明:

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

余额充值