Springboot事务失效的几种情况解读

 更新时间:2023年10月19日 10:04:08   作者:Eocc  
这篇文章主要介绍了Springboot事务失效的几种情况解读,因为Spring AOP默认使用动态代理,会给被代理的类生成一个代理类,事务相关的操作都通过代理来完成,使用内部方法调用时,使用的是实例调用,没有通过代理类调用方法,因此事务不会检测到失败,需要的朋友可以参考下

1. 内部调用

使用一个没有事务的方法调用一个有事务的方法,失败后不会进行回滚:

@Transactional
public int update(Admin admin) {
    int update = mapper.update(admin);
    return update;
}

public int invokeUpdate(Admin admin) {
    return update(admin);
}

这时因为Spring AOP默认使用动态代理,会给被代理的类生成一个代理类,事务相关的操作都通过代理来完成,使用内部方法调用时,使用的是实例调用,没有通过代理类调用方法,因此事务不会检测到失败。

解决方法就是使用代理类调用事务方法:

在类内部注入本类

@Autowired
private AdminService service;

// 然后再调用
public int invokeUpdate(Admin admin) {
    return service.update(admin);
}

通过ApplicationContext引入

((AdminService)ApplicationContext.getBean("adminService")).invokeUpdate(Admin admin);

通过AopContext引入

((AdminService)AopContext.currentProxy()).invokeUpdate(Admin admin);

2. 没有指定监听的Exception

@Transactional只会监听RuntimeException,当抛出其他异常时,不能正常捕获,也就不会回滚。

解决方法:

  • 手动捕获异常,然后包装为RuntimeException抛出
  • 使用roobackFor属性指定需要捕获的异常:
@Transactional(rollbackFor = Exception.class)
public int update(Admin admin) {
    int update = mapper.update(admin);
    return update;
}

3. 内部异常被catch

源码:org.springframework.transaction.interceptor.TransactionAspectSupport#invokeWithinTransaction

关键部分:

 try {
     //开启事务
     //这个地方也可以看出是通过代理来实现的事物,如果绕过代理调用(如内部调用),则不会开启事务
     Object var8 = invocation.proceedWithInvocation();
     return var8;
 } catch (Throwable var13) {
     //如果抛出异常,回滚事务
     //如果异常在方法内部被catch了,这个地方就不会接收到异常,就不会回滚事务
     if (txAttr.rollbackOn(var13)) {
         if (var13 instanceof RuntimeException) {
             throw (RuntimeException)var13;
         }
         throw new TransactionAspectSupport.ThrowableHolderException(var13);
     }
     throwableHolder.throwable = var13;
     var9 = null;
 } finally {
     //提交事务
     this.cleanupTransactionInfo(txInfo);
 }

到此这篇关于Springboot事务失效的几种情况解读的文章就介绍到这了,更多相关Springboot事务失效内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 详解Java线程池的使用及工作原理

    详解Java线程池的使用及工作原理

    在日常开发过程中总是以单线程的思维去编码,没有考虑到在多线程状态下的运行状况.由此引发的结果就是请求过多,应用无法响应.为了解决请求过多的问题,又衍生出了线程池的概念.本文记录了Java中线程池的使用及工作原理,需要的朋友可以参考下
    2021-05-05
  • Spring Cloud动态配置刷新RefreshScope使用示例详解

    Spring Cloud动态配置刷新RefreshScope使用示例详解

    这篇文章主要为大家介绍了Spring Cloud动态配置刷新RefreshScope使用示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-08-08
  • Java中hutool List集合对象拷贝案例代码

    Java中hutool List集合对象拷贝案例代码

    这篇文章主要给大家介绍了关于Java中hutool List集合对象拷贝的相关资料,介绍了如何将两个不同对象(Point和CustomData)的特定字段拷贝到一个中间对象(IotDataCache)中,并讨论了一些在实现过程中遇到的问题和解决方法,需要的朋友可以参考下
    2024-11-11
  • Java生成Markdown格式内容完整代码示例

    Java生成Markdown格式内容完整代码示例

    这篇文章主要介绍了将Java对象数据生成为Markdown文本,并提供了一个MarkdownUtil工具类进行处理,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2025-03-03
  • java中关于移位运算符的demo与总结(推荐)

    java中关于移位运算符的demo与总结(推荐)

    下面小编就为大家带来一篇java中关于移位运算符的demo与总结(推荐)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-05-05
  • springboot @Valid注解对嵌套类型的校验功能

    springboot @Valid注解对嵌套类型的校验功能

    这篇文章主要介绍了springboot~@Valid注解对嵌套类型的校验,主要介绍 @Valid在项目中的使用,需要的朋友可以参考下
    2018-05-05
  • Java基于fork/koin类实现并发排序

    Java基于fork/koin类实现并发排序

    这篇文章主要介绍了Java基于fork/koin类实现并发排序,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-02-02
  • Java泛型常见面试题(面试必问)

    Java泛型常见面试题(面试必问)

    泛型在java中有很重要的地位,在面向对象编程及各种设计模式中有非常广泛的应用。java泛型知识点也是Java开发岗位必问的一个话题,今天小编就给大家普及下Java泛型常见面试题,感兴趣的朋友一起看看吧
    2021-06-06
  • java中驼峰与下划线的写法互转

    java中驼峰与下划线的写法互转

    这篇文章主要介绍了java中驼峰与下横线的写法互转方法,文中先是进行了简单的介绍,之后跟大家分享了一个自己编写的工具类的示例代码,有需要的朋友可以参考借鉴,下面来一起学习学习吧。
    2017-01-01
  • Java中串行接口调用优化方式

    Java中串行接口调用优化方式

    这篇文章主要介绍了Java中串行接口调用优化方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-05-05

最新评论