当前位置: 首页 > news >正文

Spring事务失效六大场景

引言

Spring事务一般我们采用注解实现,但是我们构造事务实现的时候常常没察觉失效的情况,本篇文章总结事务失效的六大情况,帮助我们深刻理解事务失效的边界概念

1.  方法自调用

这个主要是针对声明式事务的,经过前面的介绍,小伙伴们其实也能够看出来,声明式事务底层其实就是 AOP,所以在声明式事务中,我们我们拿到的服务类并不是服务类本身,而是一个代理对象,在这个代理对象中的代理方法中,自动添加了事务的逻辑,所以如果我们直接方法自调用,没有经过这个代理对象,事务就会失效。

我写一段伪代码小伙伴们一起来看下:

public class UserService{@Transactionalpublic void sayHello(){}
}

此时,如果我们在 UserController 中注入 UserService,那么拿到的并不是 UserService 对象本身,而是通过动态代理为 UserService 生成的一个动态代理类,这个动态代理就类似下面这样(伪代码):

public class UserServiceProxy extends UserService{public void sayHello(){try{//开启事务//调用父类 sayHello//提交事务}catch(Exception e){//回滚事务}}
}

所以你最终调用的并不是 UserService 本身的方法,而是动态代理对象中的方法。

因此,如果存在这样的代码:

public class UserService{@Transactionalpublic void sayHello(){}public void useSayHello(){sayHello();}
}

在 useSayHello 中调用 sayHello 方法,sayHello 方法上虽然有事务注解,但是这里的事务不生效(因为调用的不是的动态代理对象中的 sayHello 方法,而是当前对象 this 的 sayHello 方法)。

 

2.  异常被捕获

如果我们在 sayHello 方法中将异常捕获了,那么动态代理类中的方法,就感知不知道目标方法发生异常了,自然也就不会自动处理事务回滚了。还是以前面的 UserServiceProxy 为例:

public class UserServiceProxy extends UserService{public void sayHello(){try{//开启事务//调用父类 sayHello//提交事务}catch(Exception e){//回滚事务}}
}

如果调用调用父类 sayHello的时候,sayHello 方法自动将异常捕获了,那么很明显,这里就不会进行异常回滚了。 

3. 方法非 public

这个算是 Spring 官方的一个强制要求了,声明式事务方法只能是 public,对于非 public 的方法如果想用声明式事务,那得上 AspectJ。

4. 非运行时异常

这个前面 5.3 小节介绍过了,默认情况下,只会捕获 RuntimeException,如果想扩大捕获范围,可以自行配置。

5. 不是 Spring Bean

基于 6.1 小节的理解,来看这个应该也很好懂。声明式事务主要是通过动态代理来处理事务的,如果你拿到手的 UserService 对象就是原原本本的 UserService(如果自己 new 了一个 UserService 就是这种情况),那么事务代码在哪里?没有事务处理的代码,事务自然不会生效。

声明式事务的核心,就是动态代理生成的那个对象,没有用到那个对象,事务就没戏。

6. 数据库不支持事务

这个没啥好说,数据库不支持,Spring 咋配都没用。

总结

Spring 事务常以注解实现,但存在多种可能导致失效的情况。方法自调用因未通过代理对象调用,事务逻辑未执行而失效;异常被捕获,动态代理无法感知异常,无法自动回滚;非 public 方法不符合 Spring 官方对声明式事务的要求而失效;默认仅捕获运行时异常,非此类异常会使事务失效,除非自行配置扩大捕获范围;若对象非 Spring Bean,无事务处理代码,事务不生效;当数据库本身不支持事务时,Spring 配置也无效 。

http://www.lryc.cn/news/543837.html

相关文章:

  • 【缓冲区】数据库备份的衍生问题,缓冲区在哪里?JVMor操作系统?(二)
  • 如何免费使用稳定的deepseek
  • 钉钉小程序(企业内部应用)开发--钉钉小程序web-view嵌套H5与小程序之间的通信(H5跳转钉钉小程序小程序postMessage)
  • 超级免费/牛的图片格式转换工具jpg/jpeg/png
  • 毛泽东思想“活的灵魂”
  • RabbitMQ系列(三)基本概念之Consumer
  • 天梯L2-003 月饼
  • 使用DeepSeek/ChatGPT等AI工具辅助编写wireshark过滤器
  • 常用的AI文本大语言模型汇总
  • 《深度剖析:特征工程—机器学习的隐秘基石》
  • 解决npm run dev报错
  • 教你通过腾讯云AI代码助手,免费使用满血版deepseek r1,还可以自定义知识库!
  • 【C++/数据结构】栈的模拟实现
  • StarRocks 开发环境搭建踩坑指北之存算分离篇
  • C++ Qt常见面试题(2):QT中的文件流(QTextStream)和数据流(QDataStream)的区别
  • Linux驱动学习(三)--字符设备架构与注册
  • 软件工程应试复习(考试折磨版)
  • 【JAVAEE】多线程
  • 5.10 P-Tuning v2:多层级提示编码的微调革新
  • LLM中的Benchmark是什么
  • PMP项目管理—整合管理篇—6.实施整体变更控制
  • 深度学习之特征提取
  • Gurobi 并行计算的一些问题
  • 堆、栈、最小堆
  • 基于 Spring AI 的 HIS 系统智能化改造
  • React进阶之前端业务Hooks库(五)
  • 常见锁类型介绍
  • Java中,Scanner和System.out超时的解决方法及原理
  • 一种数据高效具身操作的原子技能库构建方法
  • 云创智城YunCharge 新能源二轮、四轮充电解决方案(云快充、万马爱充、中电联、OCPP1.6J等多个私有单车、汽车充电协议)之新能源充电行业系统说明书