spring事务失效

常见场景

1、方法内的自调用

方法b是事务方法,在同一个类中,方法a使用this.b()调用

分析:

  • Spring事务的本质 :Spring声明式事务(@Transactional)是通过 AOP动态代理 实现的。容器在创建Bean时,如果检测到@Transactional注解,会生成一个代理对象(Proxy),代理对象在目标方法执行前后,会添加开启事务、提交或回滚事务的逻辑。

  • this 调用的问题 :当在方法a中通过this.b()调用方法b时,这个调用发生在 原始对象内部 ,而不是通过外部代理对象调用。因此,b方法的执行不会经过代理,事务相关的增强逻辑(开启、提交、回滚)被直接绕过了。

  • 最终结果 :方法b的事务配置(@Transactional)不会生效,它表现为一个普通方法,即使抛出了RuntimeException,数据也不会回滚。

2、方法是private

Spring 声明式事务的本质是 AOP(面向切面编程),通过动态代理为目标对象生成一个代理对象,在代理对象中织入事务管理的增强逻辑。

  • JDK 动态代理 :只能代理实现了接口的类,并且只能增强 public 方法。

  • CGLIB 动态代理 :通过生成目标类的子类来实现代理,但无法重写 private 方法。

因此,无论使用哪种代理方式,private 方法都无法被代理对象拦截,事务增强逻辑自然无法织入。

3、异常被捕获

  • 回滚触发条件 :Spring通过AOP代理拦截方法执行,当方法抛出RuntimeException或Error(默认)时,事务管理器会标记当前事务为回滚,并在方法结束时执行回滚。

  • 异常被吞没 :如果业务代码用try-catch捕获了异常,并且没有重新抛出,那么代理层感知不到异常,会认为方法正常执行完成,事务管理器也就不会触发回滚

4、事务传播机制不正确

外层方法传播机制**REQUIRES,而内层方法传播机制是REQUIRES_NEW,内层方法执行完后触发异常,内层方法的事务不会被回滚**

其他场景

1、事务方法使用了final修饰

代理方式 方法为 final 时事务是否生效 根本原因
JDK 动态代理 ❌ 失效 JDK代理基于接口,final方法无法被代理接口继承,代理对象无法拦截。
CGLIB 动态代理 ❌ 失效 CGLIB通过生成子类实现代理,final方法无法被子类重写,代理对象无法织入增强逻辑。

2、数据库不支持事务

如使用了mysql的MyISAM引擎

3、类没有被spring托管

4、使用rollback指定了异常,而方法内部抛出的是另外一种异常

事务的传播机制

事务传播机制(Propagation)定义了当一个事务方法被另一个事务方法调用时,当前事务如何与调用方的事务协同工作 。这是Spring在@Transactional注解中通过propagation属性来控制的。

传播级别 核心行为 一句话总结
REQUIRED(默认) 如果当前存在事务,则加入该事务;否则新建一个事务。 "有就加入,没有就新建"
REQUIRES_NEW 无论当前是否存在事务,都新建一个独立事务。如果当前有事务,则将其挂起。 "永远新建,互不影响"
NESTED 如果当前存在事务,则在嵌套事务中执行;否则新建事务。 "有就嵌套,没有就新建"(子事务回滚不影响主事务,但主事务回滚会影响子事务)
SUPPORTS 如果当前存在事务,则加入;否则以非事务方式执行。 "有就加入,没有就算了"
NOT_SUPPORTED 以非事务方式执行,如果当前存在事务则挂起。 "强制非事务"
MANDATORY 必须在一个已有事务中执行,否则抛出异常。 "必须有人带我玩"
NEVER 必须在非事务环境中执行,否则抛出异常。 "拒绝任何事务"
相关推荐
_Evan_Yao9 小时前
Redis 缓存穿透、击穿、雪崩,一次讲清!
java·spring·mybatis
梓豪csd9 小时前
消息订阅中心:谁该收到哪条通知
java·开发语言·人工智能·低代码·自动化·1024程序员节
秋饼9 小时前
Spring AI 2.1 Message Parts 深度实战:推理签名回放与跨轮记忆持久化的源码级落地
java·ai·技术分享·后端开发
thefool11226610 小时前
TCP 1
java·1024程序员节
不脱发的程序猿11 小时前
纳指ETF量化策略
数据库·人工智能·1024程序员节
程序员塔塔喵12 小时前
【MySQL篇|第一篇】索引失效的情况
数据库·mysql·索引失效
北京青蓝智慧马老师12 小时前
比外部黑客更难防的,是那个有权限的自己人(3 个脱敏复盘)
大数据·数据库·人工智能
金銀銅鐵12 小时前
[Java] 用 GUI 展示 EnumSet 增减元素时的内部变化(下)
java·后端·ai编程
AI人工智能+电脑小能手12 小时前
一次请求打几个下游,这个Java并行任务工具类6个方法按序聚合
java·线程池·并发编程·1024程序员节·批量处理·并行任务
笃行35013 小时前
拆一台数据集成产品:KFS 的骨架、肌肉和神经
数据库