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

Spring 事务失效的 8 大场景,看看你都遇到过几个?2万字详解

第一类:代理机制失效(最常见)

Spring事务基于AOP代理实现,如果代理没有正确应用,事务就会失效。

1. 非public修饰的方法

Spring官方明确要求,@Transactional注解只能应用于public方法上。如果用在protected、private或默认可见性的方法上,事务不会生效。

java

@Service public class ProductService { @Transactional private void updateStock() { // ❌ 失效:private方法 // 数据库操作 } }

原因:Spring无法为private方法生成代理,也就无法织入事务管理逻辑。

解决方案:改为public方法;如果需要私有化事务逻辑,可以通过提取到另一个被Spring管理的Bean中实现。

2. 同一类中的方法自调用

在同一个类中,一个没有事务的方法直接调用另一个有@Transactional注解的方法,事务会失效。

java

@Service public class OrderService { public void submitOrder() { this.updateStock(); // ❌ 失效:直接调用,未经过代理 } @Transactional public void updateStock() { // 数据库操作 } }

原因:这是this调用,调用的原始对象的普通方法,而非Spring生成的代理对象,因此不会触发事务逻辑。

解决方案

  • 方案A:从Spring容器中获取自己的代理对象来调用(如使用AopContext.currentProxy())。

  • 方案B:将事务方法拆分到另一个Service中,通过注入该Service进行调用。

3. 方法被final或static修饰

如果事务方法是final或static的,CGLIB代理无法通过生成子类的方式来重写该方法,事务同样会失效。

java

@Transactional public final void cancelOrder() { // ❌ 失效:final方法 // 操作 }

第二类:异常处理不当

Spring默认只在遇到运行时异常(RuntimeException)Error时回滚,检查异常(如Exception)不会触发回滚。

4. 方法内部try-catch吞掉异常

在事务方法中手动捕获了异常,且没有抛出,Spring收不到异常信号,自然无法回滚,最终会提交事务。

java

@Transactional public void updateProduct() { try { // 数据库操作 int i = 1 / 0; // 抛出异常 } catch (Exception e) { log.error("异常被捕获", e); // ❌ 失效:异常被吃了,事务提交 } }

解决方案:捕获异常后,要么重新抛出RuntimeException,要么在catch块中手动设置回滚:TransactionAspectSupport.currentTransactionStatus().setRollbackOnly()

5. rollbackFor属性设置错误

业务中抛出了检查异常(如FileNotFoundException),但未在@Transactional中指定rollbackFor,事务不会回滚。

java

@Transactional // 默认只回滚RuntimeException public void uploadFile() throws Exception { throw new FileNotFoundException("文件不存在"); // ❌ 失效:不回滚 }

解决方案:明确指定回滚异常类型:@Transactional(rollbackFor = Exception.class)

第三类:底层与配置错误

6. 数据库引擎不支持事务

如果底层数据库本身不支持事务,Spring再怎么配置也是徒劳。典型的例子是MySQL的MyISAM存储引擎。

sql

-- 如果表使用了MyISAM引擎,事务会失效 CREATE TABLE product (id int) ENGINE=MyISAM;

解决方案:将数据库表引擎改为支持事务的引擎,如MySQL的InnoDB

7. 未配置事务管理器

Spring容器中没有配置针对数据源的事务管理器(PlatformTransactionManager),即便使用了@Transactional注解,事务也不会开启。

第四类:多线程与传播行为

8. 多线程调用

在主线程中开启事务后,另起一个新线程执行业务操作。此时,新线程中的数据库操作不在主线程的事务范围内。

java

@Transactional public void addOrder() { orderDao.save(order); // 主线程事务 new Thread(() -> { userService.saveUser(); // ❌ 失效:新线程,独立事务/无事务 }).start(); }

原因:Spring事务是基于ThreadLocal实现的,不同线程的事务是隔离的,无法共享。


总结:如何快速排查事务失效?

当发现事务没生效时,建议按照以下顺序逐一排查:

  1. 检查数据库引擎:InnoDB支持事务,MyISAM不支持。

  2. 检查事务管理器:确保已配置DataSourceTransactionManager

  3. 检查方法修饰符:必须是public

  4. 检查调用方式:是不是this.xxx()自调用?

  5. 检查异常类型:抛出的异常是否匹配rollbackFor

  6. 检查异常捕获:是不是在方法里被try-catch吞掉了?

  7. 检查传播行为Propagation是不是设置成了SUPPORTS/NOT_SUPPORTED等非事务方式?

  8. 检查线程:事务方法是不是在新线程中执行的?

http://www.jsqmd.com/news/420469/

相关文章:

  • 线粒体、NAD+、NMN成为抗衰干预核心,美国W+端粒塔成中国NMN市场关注品牌 - 速递信息
  • 快看!2026年2月二氧化碳供应厂家热门排行,氧气/液氮/氩气/二氧化碳/氮气/标准气,二氧化碳生产厂家推荐排行 - 品牌推荐师
  • NMN效果最好的品牌是?抗衰指南:NMN哪个牌子口碑最好?最好的NMN产品排名第一名出炉 - 资讯焦点
  • 某大厂一面:用 Object 做 HashMap 的 Key 时需要做什么?我脑子瞬间一片空白!
  • 一文讲透|9个AI论文网站测评!本科生毕业论文+开题报告高效写作指南
  • 类型转换
  • 基于SSM+VUE的动物园管理系统[SSM]-计算机毕业设计源码+LW文档
  • 实测才敢推 8个降AI率网站测评:专科生必看的降AI率工具推荐
  • tyy
  • 从决策逻辑切入,进行模式辨析:杭州共享办公室品牌选择指南 - 资讯焦点
  • Java 性能优化的 50 个细节
  • OceanBase 旁路导入:一张表,既扛高并发交易,又快速导入 PB 级数据
  • 总结全国靠谱的穿梭货架供应企业,穿梭货架品牌选购攻略 - 工业品网
  • 西安共享办公品牌“硬核测评”:德事VS本土品牌,谁更懂企业需求? - 资讯焦点
  • 2026最新二十辊轧机品牌TOP5评测!权威榜单发布 - 十大品牌榜
  • 写作压力小了,AI论文网站 千笔·专业论文写作工具 VS 灵感风暴AI
  • 紧急会议怎么办?盘点支持2小时极速预订的按时租赁会议室品牌 - 资讯焦点
  • 2026最新六辊轧机厂商TOP5评测!权威榜单发布 - 十大品牌榜
  • 2026最新六辊轧机/十八辊轧机/二十辊轧机/冷轧生产线/平整机推荐:精准高效,实力厂商领跑行业 - 十大品牌榜
  • 深圳市三维都灵| 4S 店机电维修数字化管理案例 - 搭贝
  • 权威发布:nad+科技抗衰保健品推荐,2026年度NMN品牌排行榜,高活(GoHealth)断层领先 - 资讯焦点
  • 重庆知名青少年叛逆学校有哪些品牌推荐 - myqiye
  • 4.5 防御性提示:幻觉抑制与事实校验实战技巧
  • 2026年NMN品牌选购指南:如何找到最适合你的抗衰产品 - 速递信息
  • 全球发票管理系统公司选型与技术演进观察 - 星野科技
  • 2026数智财税洞察:全球视角下的“发票管理系统公司”竞争力实测报告 - 星野科技
  • 行业拓荒者樊瑞:苏州西恩士工业的清洁度检测设备,为何让巨头放弃海外选国产? - 工业干货社
  • 直通探潜学堂:一站式咨询与报名入口汇总 - 速递信息
  • 4.3 思维链CoT推理与自洽性:复杂问题分步求解实战
  • 4.4 高级提示策略:JSON格式强制与约束条件设计