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-11-11
  • Springboot整合activemq的方法步骤

    Springboot整合activemq的方法步骤

    这篇文章主要介绍了Springboot整合activemq的方法步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-01-01
  • Java中的for循环结构及实例

    Java中的for循环结构及实例

    这篇文章主要介绍了Java中的for循环结构及实例,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-01-01
  • Mybatis-Plus时间范围查询方式详解

    Mybatis-Plus时间范围查询方式详解

    这篇文章主要介绍了Mybatis-Plus时间范围查询方式详解,通过两种方式结合实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-09-09
  • Java线程编程中Thread类的基础学习教程

    Java线程编程中Thread类的基础学习教程

    这篇文章主要介绍了Java线程编程中Thread类的基础学习教程,Thread类包含诸多操作线程的方法,非常重要,需要的朋友可以参考下
    2015-12-12
  • 深入理解Java设计模式之享元模式

    深入理解Java设计模式之享元模式

    这篇文章主要介绍了JAVA设计模式之享元模式的的相关资料,文中示例代码非常详细,供大家参考和学习,感兴趣的朋友可以了解下
    2021-11-11
  • 利用Java如何实现将二维数组转化为链式储存

    利用Java如何实现将二维数组转化为链式储存

    链式结构不要求逻辑上相邻的节点在物理位置上也相邻,节点间的逻辑关系是由附加的指针字段表示的,通常借助于程序设计中的指针结构来实现,这篇文章主要给大家介绍了关于利用Java如何实现将二维数组转化为链式储存的相关资料,需要的朋友可以参考下
    2021-12-12
  • java调用通义千问API的详细完整步骤

    java调用通义千问API的详细完整步骤

    通义千问是阿里云自主研发的大语言模型,能够在用户自然语言输入的基础上,通过自然语言理解和语义分析,理解用户意图,在不同领域、任务内为用户提供服务和帮助,下面这篇文章主要给大家介绍了关于java调用通义千问API的详细完整步骤,需要的朋友可以参考下
    2024-02-02
  • 聊聊@RequestParam,@PathParam,@PathVariable等注解的区别

    聊聊@RequestParam,@PathParam,@PathVariable等注解的区别

    这篇文章主要介绍了聊聊@RequestParam,@PathParam,@PathVariable等注解的区别,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-02-02
  • Java enum的用法详细介绍及实例代码

    Java enum的用法详细介绍及实例代码

    这篇文章主要介绍了Java enum的用法详细介绍及实例代码的相关资料,需要的朋友可以参考下
    2017-02-02

最新评论