首页 > 其他分享 >Spring事务:异常不回滚、marked as rollback-only无法提交

Spring事务:异常不回滚、marked as rollback-only无法提交

时间:2024-09-05 17:36:59浏览次数:5  
标签:事务 调用 rollback Spring Exception marked 异常 public

1、非代理对象调用事务方法时事务不生效

A实现了接口IA,类A的方法a()上使用@Transaction声明了事务,想要在调用该方法时,使a()的事务生效,就必须使用类A的Aop代理对象来调用。

1)正常情况下,我们在类B中注入A的Bean对象,这个对象就是代理对象,使用该对象调用a()方法时,a()的事务是正常生效的。

2)另一个常见情况就是类A中的方法a1()中直接调用事务方法a(),无论是a()还是this.a(),此时调用方法a()的不是代理对象,而是类A的原生对象,这种情况下,a()的事务是不生效的,也就是a()中发生异常事务不会回滚。如果想要在这个情况下让a()的事务生效,我们需要拿到类A的Aop代理对象。首先在配置类中使用@EnableAspectJAutoProxy(exposeProxy = true)暴露代理对象,再在代码中使用IA iA = (IA)AopContext.currentProxy();获取到类A的代理对象iA,再使用iA调用方法a(),此时a()的事务就是生效的。

@Service
public class A implements IA {

  @Override
  @Transactional(rollback = Exception.class)
  public void a(){
    // 代码块
  }
  
  @Override
  @Transactional
  public void a1(){
    // 原生对象调用
    a(); // 方法a()事务不生效

    // 代理对象调用
    IA iA = (IA)AopContext.currentProxy();
    iA.a(); // 方法a()事务生效
  }
}

@Component
public class B {
  
  @Autowired
  private IA iA;
  
  public void b() {
    iA.a(); // 方法a()事务生效
  }
}

/**
 * 启动类(配置类)
 */
@SpringBootApplication
@EnableTransactionManagement(proxyTargetClass = true) // proxyTargetClass:ture cglib代理,false jdk动态代理
@EnableAspectJAutoProxy(exposeProxy = true) // 开启暴露代理对象
public class TestApplication {
    public static void main(String[] args) {
        SpringApplication.run(TestApplication .class,args);
        System.out.println("(♥◠‿◠)ノ゙  启动成功   ლ(´ڡ`ლ)゙ ");
    }
}

2、异常Transaction rolled back because it has been marked as rollback-only的触发原因和解决方式

这个异常往往是在代码执行完成最后提交事务时抛出的,所以我们无法直接定位异常的源头。

在事务方法中,遇到异常便会触发回滚,如果我们不想回滚,就会使用try catch包裹住可能抛出异常的代码块。

但有一种情况,就算在代码中捕获了所有异常,但执行到最后还是会碰到标题所示的异常,导致事务提交失败。这是因为我们在事务生效的方法a()中调用事务生效的方法b(),并且有时为了不让b()的异常影响a()的提交,我们会在a()中用try catch包裹住了b()的调用。但实际上,如果b()中发生了异常,异常被捕获,后续代码正常执行,但最后还是会碰到标题的异常。这是因为a()b()处在同一事务中,如果在b()或者b()中调用的与其处在同一事务中的下级方法中出现了异常但没有被抛给事务管理器时,这个事务就会被标记为rollback-only,到最后事务提交时,才会提示异常。

如果想要解决这个问题,并且依旧不想让b()的异常抛出,我们只需要让a()b()不处在同一事务中就可以了,@Transaction的propagation属性默认值是REQUIRED,意思是当前有事务则加入,没有则创建一个事务,就是这个配置让a()b()处在同一事务中,所以,我们只要把b()的事务改成@Transactional(propagation = Propagation.NESTED),使b()创建一个嵌套事务并加入,此时b()的异常就不会导致a()回滚,并且不会遇到标题的异常。

@Service
public class A implements IA {

  @Autowired
  private IB iB;

  @Override
  @Transactional(rollback = Exception)
  public void a(){
    try{
      iB.b();
    } catch(Exception e) {
      // ...
    }
  }
}

@Service
public class B implements IB {
  
  @Override
  @Transaction(rollback = Exception)
  // @Transaction(rollback = Exception, propagation = Propagation.NESTED) // 解决方法1,嵌套事务
  // @Transaction(rollback = Exception, propagation = Propagation.REQUIRES_NEW) // 解决方法2,全新事务
  // @Transaction(rollback = Exception, propagation = Propagation.NOT_SUPPORTED) // 解决方法3,关闭事务
  public void b() {
    throw new RuntimeException();
  }

  /**
   * 本类方法中调用时注意,一般情况的调用方式不会触发rollback-only异常
   */
  @Override
  @Transactional(rollback = Exception)
  public void b1(){
    // 原生对象调用
    try{
      b(); // 方法b()事务不生效,不会触发rollback-only异常
    } catch(Exception e) {
      // ...
    }

    // 代理对象调用
    IB iB = (IB)AopContext.currentProxy();
    try{
      iB.b(); // 方法b()事务生效,会触发rollback-only异常
    } catch(Exception e) {
      // ...
    }
  }
}

标签:事务,调用,rollback,Spring,Exception,marked,异常,public
From: https://www.cnblogs.com/bear-blog/p/18398919

相关文章

  • Java项目: 基于SpringBoot+mysql蜗牛兼职网兼职平台管理系统(含源码+数据库+答辩PPT+
    一、项目简介本项目是一套基于SpringBoot+mysql蜗牛兼职网兼职平台管理系统包含:项目源码、数据库脚本等,该项目附带全部源码可作为毕设使用。项目都经过严格调试,eclipse或者idea确保可以运行!该系统功能完善、界面美观、操作简单、功能齐全、管理便捷,具有很高的实际应用......
  • 入门Spring6
    1.像web一样创建maven项目,然后像pom.xml里导入springjuint的依赖2.如何不用new出对象而且可以使用对象首先得在resource里创建Spring得bean.xml里面得配置为首先有两种方法实(1)左边得代码为publicvoidtest(){ApplicationContextcontext=newClassPathXmlApplic......
  • 基于django+vue与spring的药品销售管理系统设计与实现【开题报告+程序+论文】计算机毕
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表开题报告内容研究背景随着医药行业的快速发展与市场竞争的日益激烈,药品销售管理成为医药企业提升运营效率、保障药品质量、优化客户服务的关键环节。传统的手工......
  • Spring Boot:医护人员排班系统开发的技术优势
    2相关技术2.1MYSQL数据库MySQL是一个真正的多用户、多线程SQL数据库服务器。是基于SQL的客户/服务器模式的关系数据库管理系统,它的有点有有功能强大、使用简单、管理方便、安全可靠性高、运行速度快、多线程、跨平台性、完全网络化、稳定性等,非常适用于Web站点或者其他......
  • 医护人员排班系统:Spring Boot技术实现细节
    2相关技术2.1MYSQL数据库MySQL是一个真正的多用户、多线程SQL数据库服务器。是基于SQL的客户/服务器模式的关系数据库管理系统,它的有点有有功能强大、使用简单、管理方便、安全可靠性高、运行速度快、多线程、跨平台性、完全网络化、稳定性等,非常适用于Web站点或者其他......
  • 计算机毕业设计springboot+vue3便民医疗服务预约系统 原生微信小程序
    目录博主介绍技术栈开发核心技术具体实现截图前端后端java类核心代码部分展示可行性论证技术可行性详细视频演示系统测试实现思路源码获取博主介绍......
  • 毕业设计:基于微信小程序的点餐系统(Springboot)【代码+论文+PPT】
    全文内容包括:1、采用技术;2、系统功能;3、系统截图;4、配套内容。索取方式见文末微信号,欢迎关注收藏!一、采用技术语言:Java1.8框架:SSM数据库:MySQL5.7、8.0开发工具:IntelliJIDEA旗舰版其他:Maven3.8以上二、系统功能用户管理:负责注册、登录、个人信息修改及用户权限设置等功能......
  • springboot接入prometheus监控
    pom引入org.springframework.bootspring-boot-starter-actuatorio.micrometermicrometer-coreio.micrometermicrometer-registry-prometheus1.5.6yaml配置management.endpoints.web.exposure.include=*management.endpoints.web.base-path=/actuatormanagement......
  • 熔断、限流、降级 —— SpringCloud Hystrix
    概述Hystrix为微服务架构提供了一整套服务隔离、服务熔断和服务降级的解决方案。它是熔断器的一种实现,主要用于解决微服务架构的高可用及服务雪崩等问题Hystrix的特性如下:服务熔断:Hystrix熔断器就像家中的安全阀一样,一旦某个服务不可用,熔断器就会直接切断该链路上的请求,避......
  • 基于SpringBoot+Vue的高校宣讲会管理系统(带1w+文档)
    基于SpringBoot+Vue的高校宣讲会管理系统(带1w+文档)基于SpringBoot+Vue的高校宣讲会管理系统(带1w+文档)高校宣讲会管理系统可以对高校宣讲会管理系统信息进行集中管理,可以真正避免传统管理的缺陷。高校宣讲会管理系统是一款运用软件开发技术设计实现的应用系统,在......