@Transactional 事务失效 8 大场景

发布时间:2026/10/14 21:23:18

@Transactional 事务失效 8 大场景 前言Transactional声明式事务是 Spring 开发最常用的功能很多人以为只要加上注解就能自动开启事务、异常自动回滚。但在项目中经常遇到代码抛异常了数据库数据依然提交造成脏数据引发线上事故。根本原因Spring 声明式事务是基于 AOP 动态代理实现的。只有经过代理对象调用方法事务拦截器TransactionInterceptor才会在方法前后拦截开启 / 提交 / 回滚事务。一旦绕过代理事务直接失效。核心一句话事务生效的前提方法由 Spring 代理对象调用且 Spring 能捕获到抛出的异常。一、原理前置Spring 事务执行流程Spring 启动时扫描Transactional注解为 Bean 创建代理对象JDK 代理 / CGLIB 代理外部调用代理对象方法 → 进入TransactionInterceptor事务拦截器拦截器先获取事务属性开启事务执行目标方法方法执行完毕无异常提交事务抛出指定异常执行回滚如果没有走代理对象直接调用目标对象原生方法拦截器完全不会执行注解等于不存在。二、八大失效场景代码 原理 解决方案场景 1注解加在非 public 方法上错误代码Service public class OrderService { Autowired private OrderMapper orderMapper; // private方法事务失效 Transactional private void createOrder() { orderMapper.insert(new Order()); int i 1 / 0; } }原因Spring 源码AbstractFallbackTransactionAttributeSource#computeTransactionAttribute会做判断如果方法不是 public直接返回 null不解析事务属性AOP 不会生成事务增强。 JDK 动态代理本身就只能代理 public 方法CGLIB 虽然可以代理非 public但 Spring 事务框架强制校验访问权限。解决方案事务方法必须定义为public。场景 2同类内部自调用this 调用事务方法最高频踩坑错误代码Service public class OrderService { Autowired private OrderMapper orderMapper; public void outerMethod() { // this调用调用的是原生对象不是代理对象事务失效 this.innerTransactionalMethod(); } Transactional public void innerTransactionalMethod() { orderMapper.insert(new Order()); int i 1 / 0; } }原因this指向原始目标对象不是 Spring 容器生成的代理对象调用时不会经过 AOP 事务拦截器。很多人写代码习惯在同一个 service 内部调用事务方法90% 踩坑。三种解决方案推荐顺序拆分到不同 Service最优代码清晰无副作用本类注入自己Autowired private OrderService self;用self.innerTransactionalMethod()调用通过 Spring 上下文获取代理对象不推荐侵入性强注意自调用坑面试超级高频面试官最爱问。场景 3方法内部 try-catch 捕获异常没有向上抛出错误代码Service public class OrderService { Autowired private OrderMapper orderMapper; Transactional public void createOrder() { try { orderMapper.insert(new Order()); int i 1 / 0; } catch (Exception e) { log.error(创建订单异常, e); // 异常被吃掉没有抛出给代理拦截器 } } }原因事务拦截器只能捕获方法向外抛出的异常才触发回滚。如果你在方法内部捕获所有异常拦截器感知不到发生错误正常执行事务提交。解决方案方案 1catch 处理日志后重新抛出异常catch (Exception e) { log.error(创建订单异常, e); throw new RuntimeException(e); }方案 2业务判断手动使用TransactionStatus编程式事务回滚不推荐大量使用场景 4抛出受检异常没有配置 rollbackFor错误代码Transactional public void createOrder() throws IOException { orderMapper.insert(new Order()); throw new IOException(IO异常); }原因:Spring 事务默认只对 RuntimeException 和 Error 触发回滚对于 Exception 子类受检异常 Checked Exception不会自动回滚。IOException 属于受检异常。解决方案Transactional(rollbackFor Exception.class) public void createOrder() throws IOException { orderMapper.insert(new Order()); throw new IOException(IO异常); }企业开发规范Transactional一律写上rollbackFor Exception.class避免漏掉受检异常。场景 5数据库存储引擎不支持事务MySQL MyISAM 引擎不支持事务只有 InnoDB 支持事务。 哪怕代码注解写的再正确如果表引擎是 MyISAM事务完全无效不会回滚。解决方案建表语句指定引擎ENGINEInnoDB DEFAULT CHARSETutf8mb4;生产环境 MySQL 全部使用 InnoDB。场景 6事务传播行为配置错误典型场景REQUIRES_NEW、NOT_SUPPORTED、SUPPORTS配置错误。 示例外层方法事务内层方法写Transactional(propagation Propagation.NOT_SUPPORTED)内层会挂起事务在非事务环境执行内层异常不会回滚外层数据。解决方案熟悉 7 种传播行为根据业务场景选择不要盲目复制。REQUIRED默认有事务就加入没有新建事务绝大多数场景使用REQUIRES_NEW新建独立事务挂起外层事务NESTED嵌套事务依赖外层事务提交 / 回滚场景 7多线程环境调用事务方法事务上下文丢失错误示例Transactional public void createOrder() { orderMapper.insert(order); // 新开子线程执行DB操作 new Thread(() - { orderMapper.insertLog(); int i 1 / 0; }).start(); }原因:事务底层数据库连接存放在ThreadLocal不同线程 ThreadLocal 互相隔离。子线程拿不到主线程事务连接子线程数据库操作是独立事务子线程异常不会回滚主线程的数据。解决方案:多线程下不能共用事务拆分业务或使用分布式事务方案。场景 8方法被 final、static 修饰Transactional public final void createOrder(){}CGLIB 代理原理是继承目标类并重写方法方法加 final子类无法重写无法生成代理事务注解失效。 static 方法属于类本身不属于实例对象无法被 AOP 代理事务失效。解决方案事务方法不要加 final、static三、生产环境事务编码规范总结Transactional只写在 public 方法禁止 private、final、static同 Service 内部不要用 this 自调用事务方法统一加上rollbackFor Exception.classtry-catch 捕获异常后如果需要回滚必须重新抛出异常MySQL 表必须使用 InnoDB 引擎多线程不要共用同一个事务优先拆分 Service 避免自调用少用容器自注入这种 hack 写法四、事务失效排查思路快速定位确认数据库引擎是不是 InnoDB看方法是不是 public、有没有 final/static确认调用方式是不是 this 内部调用查看异常是否被 catch 吃掉有没有向外抛出查看TransactionalrollbackFor 配置多线程场景检查 ThreadLocal 事务上下文是否传递查看 AOP 代理是否生效打印 bean 看是不是代理对象五、高频提问Q为什么同类内 this 调用 Transactional 失效 ASpring 事务基于 AOP 动态代理this 是原始对象不走代理拦截器事务不会开启。QTransactional 默认什么异常回滚 ARuntimeException 和 ErrorChecked Exception 默认不回滚需要配置 rollbackFor。总结事务失效属于 Java 后端高频坑很多初级开发只停留在 “加注解” 的层面一旦线上出现数据不一致很难快速定位。理解底层 AOP 代理原理才能从根源规避。生产环境遇到数据不一致优先排查上面 8 个场景。
延伸阅读

更多相关文章

2026/10/14 21:23:18

MySQL InnoDB MVCC 深度解析

MVCC 是 InnoDB 实现高并发事务的核心,也是 Java 后端面试高频压轴题。很多人只记住一句话 “多版本并发控制,读写不阻塞”,但一问底层:隐藏字段、undo log 版本链、ReadView 可见性规则、RC 与 RR 的区别、MVCC 到底能不能解决幻…

2026/10/14 21:23:18

numpy学习2

numpy读写文件,使用库函数进行分析问题。一维数组读取import numpy as np# numpy的简单统计分析# 一维数组 arr np.arange(100).reshape(10,10) # arange(100)取0-99共100个数字 np.save("./save_arr",arr) #保存数组,默认是.npy文件 # pri…

2026/10/15 0:02:22

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

1. 为什么选择容器化方式部署 LoRa 网络服务LoRa 物联网项目落地时,网络服务器是整个链路的核心枢纽。它负责接收网关上报的数据包、完成去重与解密、再把有效载荷分发给上层应用。早期大家习惯把网络服务器直接装在物理机上,依赖一堆系统库和特定版本的…

2026/10/15 0:02:22

铝合金仿菠萝格木纹构件|复刻珍木肌理 以铝代木筑就恒久中式雅境

在中式院墅、古建廊道与高端商业中式营造中,菠萝格木素来以温润醇厚的棕红肌理、沉稳致密的质感著称,是檐廊、立柱、门楣、雀替等构件的优选名贵硬木。然而天然菠萝格造价高昂,户外应用易开裂变形、虫蛀腐朽,常年刷漆维护成本高,让许多项目难以兼得木韵质感与长久耐用。铝合金仿…

2026/10/15 0:02:22

影刀RPA深度实战:大模型Fine-tuning定制RPA专用Prompt与指令生成

影刀RPA深度实战:大模型Fine-tuning定制RPA专用Prompt与指令生成 一、技术背景 大模型(LLM)在通用场景下表现强大,但当我们将 GPT-4 或 Qwen 直接用于生成影刀RPA操作指令和 XPath 定位时,准确率通常只有 40%-60%。原因…

2026/10/15 0:02:22

防关联浏览器哪个好?三款产品实测差异解析

新手做多店铺,最纠结的就是防关联浏览器选哪个。飞跨、网易、站斧这三款被问得最多,先给结论:要一体化省心、长期便宜,选站斧;要网易招牌和稳,选网易;预算紧做东南亚 Lazada,选飞跨。…

2026/10/14 23:41:09

从工具调用到Code Mode:AI Agent范式转移与工程实践

1. 从「工具调用」到「Code Mode」:一场正在发生的 Agent 范式转移过去一年多,我一直在做 AI Agent 相关的落地项目,从最早的 Function Calling 到后来的多工具编排,踩过的坑可以说能写满一个笔记本。但最近半年,一个明…

2026/10/14 11:31:03

Python调用Gemini Structured Outputs实现工单路由门禁

客服工单最怕的不是模型“答错一句话”,而是它给出一段看起来合理的说明,程序却从中猜错优先级。通俗做法是:要求模型只交 JSON(JavaScript Object Notation,轻量数据格式),再让代码验证它。Gem…

2026/10/14 17:41:07

Spring Boot超市进销存系统毕设实战:从需求拆解到答辩通关

最近带的一个学生项目组里,有A同学跑来问我:选什么毕设题目最稳妥,既能让评审老师觉得工作量够,又不会在答辩时被问到语无伦次。我第一反应就是推荐基于Spring Boot的超市仓库管理系统——也就是超市进销存系统。这个题目乍一看平…

2026/10/14 2:32:55

Flutter StatefulWidget 生命周期核心解析

很多刚开始接触 Flutter 的朋友,在看完一堆“Hello World”和基础组件之后,大概率都会撞上同一堵墙:StatefulWidget 里那堆 initState、build、dispose 方法,到底什么时候被调用?为什么顺序是那样?在里面到…

2026/10/15 0:02:22

防关联浏览器哪个好?三款产品实测差异解析

新手做多店铺,最纠结的就是防关联浏览器选哪个。飞跨、网易、站斧这三款被问得最多,先给结论:要一体化省心、长期便宜,选站斧;要网易招牌和稳,选网易;预算紧做东南亚 Lazada,选飞跨。…

2026/10/15 0:02:22

影刀RPA深度实战:大模型Fine-tuning定制RPA专用Prompt与指令生成

影刀RPA深度实战:大模型Fine-tuning定制RPA专用Prompt与指令生成 一、技术背景 大模型(LLM)在通用场景下表现强大,但当我们将 GPT-4 或 Qwen 直接用于生成影刀RPA操作指令和 XPath 定位时,准确率通常只有 40%-60%。原因…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑