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

被误解的 Spring 事务:它不是不存在,而是你没注意

写在前面

“我做了几个单体项目和微服务项目,感觉很少遇到 Spring 事务。好像 Spring 里面并不存在事务,只有在微服务项目中才有分布式事务。”

这是我收到的一条读者留言,也是很多初学者的共同困惑。因为感觉不到,所以认为不存在;因为没主动配置,所以觉得它可有可无。

这是一个危险的认知误区。

实际上,Spring 事务几乎是每一个涉及数据库写操作的 Java 后端项目都在默默使用的功能。你之所以“没感觉到”,恰恰是因为 Spring 把它做得太优雅、太透明了——你只需要一个@Transactional注解,剩下的它全包了。

今天,我们就来彻底拆解 Spring 事务:它到底是什么?和 MySQL 事务有什么区别?为什么会失效?以及,你该怎么用好它。

一、Spring 事务 ≠ 数据库事务,它是“管家”不是“工人”

先澄清一个核心概念:

  • MySQL 事务:是数据库层面的能力,通过BEGINCOMMITROLLBACK来控制一组 SQL 要么全部成功,要么全部失败。

  • Spring 事务:是基于 AOP 对数据库事务的封装和管理,它帮你自动开启、提交或回滚事务,让你不用手写事务模板代码。

换句话说,Spring 本身没有创造事务,它只是让使用数据库事务变得更简单

// 没有 Spring 事务时,你需要手动管理 public void transfer() { Connection conn = null; try { conn = dataSource.getConnection(); conn.setAutoCommit(false); // 执行 SQL conn.commit(); } catch (Exception e) { conn.rollback(); } finally { conn.close(); } } // 有了 Spring 事务,你只需要这样 @Transactional public void transfer() { // 执行 SQL,Spring 自动管理提交/回滚 }

所以,Spring 事务是存在的,而且一直在用。你之所以没感觉,是因为 Spring Boot 自动配置 + 默认行为让你“无感使用”了。

二、Spring 事务的核心原理:AOP 代理 + 数据库事务

Spring 事务的实现原理可以用一张图概括:

关键点:Spring 事务依赖 AOP 代理。如果代理对象调不到方法(比如内部调用),事务就会失效。

三、Spring 事务的 7 种传播行为(propagation)

这是 Spring 事务独有的概念,MySQL 事务没有。它定义了事务方法被另一个事务方法调用时,如何传播

四、Spring 事务失效的 8 大经典场景(附解决方案)

这是面试和工作中的高频痛点。

场景1:方法没有被 Spring 代理调用(内部调用)

@Service public class UserService { public void saveUser() { this.doInsert(); // ❌ 内部调用,@Transactional 失效 } @Transactional public void doInsert() { // 插入数据库 } }

解决方案:注入自身代理或拆分 Service。

@Service public class UserService { @Autowired private UserService selfProxy; public void saveUser() { selfProxy.doInsert(); // ✅ 通过代理调用 } }

场景2:方法不是 public 的

@Transactional只对public方法生效。protected、private 会被忽略。

场景3:异常被 catch 吞掉了

@Transactional public void update() { try { // 抛异常 } catch (Exception e) { // 什么都没做,事务不会回滚 } }

解决方案:要么重新抛出异常,要么手动回滚TransactionAspectSupport.currentTransactionStatus().setRollbackOnly()

场景4:抛出的异常类型不对

Spring 事务默认只回滚RuntimeExceptionErrorException不会回滚。

@Transactional public void update() throws Exception { throw new Exception("checked exception"); // ❌ 不会回滚 }

解决方案@Transactional(rollbackFor = Exception.class)

场景5:数据库引擎不支持事务

MySQL 中 MyISAM 引擎不支持事务,需要改为 InnoDB。Spring 事务无能为力。

场景6:多数据源配置错误

多个数据源时,如果没有指定事务管理器,可能用错了 DataSource。

场景7:方法被 final 或 static 修饰

AOP 代理无法覆盖 final 方法。

场景8:Spring 代理方式错误

使用 CGLIB 代理时,如果目标类没有实现接口,且代理类无法继承(比如 final 类),事务也会失效。

一张图总结事务失效场景:

五、Spring 事务 vs MySQL 事务:区别一目了然

核心结论:Spring 事务是对 MySQL 事务的“增强版遥控器”,它让你更方便地使用数据库事务,但无法超越数据库事务的物理边界。

六、开发中什么时候需要 Spring 事务?(实际场景)

场景1:单体项目中的写操作

  • 用户下单(扣库存 + 创建订单 + 减余额)

  • 银行转账(A 账户减钱,B 账户加钱)

  • 文章发布(保存文章 + 更新用户统计 + 推送消息)

这些操作如果不用事务,可能出现库存扣了订单没生成、钱扣了对方没收到等严重数据不一致。

场景2:多表关联更新

更新主表同时更新子表、日志表、关联表。

场景3:需要保证最终一致性的批量操作

批量导入数据时,要么全部成功,要么全部失败。

场景4:只读事务优化

查询方法上加@Transactional(readOnly = true),数据库会优化查询性能,Spring 也不会再检测 dirty 状态。

@Transactional(readOnly = true) public List<User> findAll() { return userMapper.selectList(); }

你之所以“感觉不到”,是因为很多业务方法默认就在事务中(Spring Boot 默认没有为每个方法开启,但你的 Service 方法可能被调用的上层有事务,或者你依赖的框架自带事务)。

七、澄清误区:Spring 事务 ≠ 分布式事务

你提到的“微服务项目中才有分布式事务”,这个理解部分正确,但需要区分:

  • Spring 事务(也叫本地事务)解决的是单个数据库连接内的一致性,比如一个方法里操作了多张表,它们都在同一个数据库。

  • 分布式事务解决的是跨多个微服务、多个数据库的一致性,比如订单服务 + 库存服务 + 积分服务。

Spring 事务在微服务项目中依然存在且常用

  • 每个微服务内部自己的数据库操作,依然需要 Spring 事务保证本地一致性。

  • 跨服务的分布式事务,则需要额外的方案(TCC、SAGA、Seata 等),Spring 事务不能解决跨服务问题。

所以,不是说微服务项目里 Spring 事务就不用了,而是每个服务内部仍然在用,只是服务之间需要更强的协调机制

八、最佳实践:用好 Spring 事务的 5 条建议

  1. 始终在 public 方法上使用@Transactional,并且从外部调用(通过代理)。

  2. 明确指定回滚异常@Transactional(rollbackFor = Exception.class),避免 checked 异常不回滚。

  3. 合理设置传播行为:默认 REQUIRED 够用,但独立日志操作可用 REQUIRES_NEW。

  4. 查询方法加上readOnly = true,提升性能且语义清晰。

  5. 避免在事务中做耗时操作(如远程调用、大量循环计算),缩短事务持有时间。

总结:事务是你默默守护数据的“隐形守护者”

回到最初的问题:Spring 事务真的存在吗?

不仅存在,而且你每天都在用——只是它太安静、太自动化,以至于你忽略了它的存在。Spring 事务就像代码世界的“隐形守护者”,在你执行写操作时,默默保证数据要么全部成功,要么全部回滚。

Spring 事务与 MySQL 事务的关系:MySQL 提供基础能力,Spring 提供优雅的使用方式。

Spring 事务与分布式事务的关系:本地事务解决单库问题,分布式事务解决跨库问题,二者不是替代,而是互补。

希望这篇文章能帮你彻底理清 Spring 事务的本质,下次面试官问“事务失效的场景”时,你不仅能说出 8 条,还能讲清楚背后的原理。

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

相关文章:

  • 如何用Move Mouse防止电脑休眠:3个实用场景配置指南
  • ioquake3控制台系统详解:100+新CVAR与命令的实用手册
  • AI翻唱技术全攻略:从环境搭建到专业级作品生成
  • 高效解决Windows更新故障:Reset Windows Update Tool全方位技术指南
  • Axure中文界面终极设置指南:3分钟告别英文困扰
  • 2026办公家具工厂直供深度选型指南:如何为企业匹配最佳方案? - 速递信息
  • LiuJuan20260223Zimage功能体验:除了画人,它还能生成龙和场景吗?
  • Qwen3-VL-8B AI聊天系统部署全攻略:从零到一,打造你的私人AI助手
  • ArcGIS投影变换
  • DAMOYOLO-S辅助的AI绘画工作流:与ComfyUI的集成实践
  • 好写作AI毕业论文功能深度解读:你不是在“用它”,而是在“训练它”
  • 如何在Parsley.js中区分警告与错误:自定义错误等级的完整指南
  • 2026年优质服装检品服务商推荐榜:广州检品公司/最好的检品公司/有实力的检品公司/正规的检品公司/比较好的检品公司/选择指南 - 优质品牌商家
  • 突破语言壁垒:御坂翻译器让Galgame实时翻译不再是难题
  • 解锁6大性能黑科技:让Bilibili-Evolved实现前所未有的流畅体验
  • AutoPOI Word模板表格导出:终极解决方案与最佳实践指南
  • 探讨口碑好的喷淋塔系统,蓝鹰环保个性化方案优势凸显 - 工业品网
  • 突破性能瓶颈:php-jwt关键性能指标设计与监控全指南
  • 在线演示文稿工具PPTist:零门槛高效创作专业幻灯片的开源解决方案
  • 必看!技术强的纺织品燃烧试验机公司大盘点 - 品牌推荐大师1
  • STM32CubeMX实战:串口通信与重定向的优化技巧
  • 3步打造高效个性化桌面效率工具:TrafficMonitor插件使用指南
  • 如何高效构建微生物共现网络:microeco包的SpiecEasi应用指南
  • OpenClaw技能开发入门:为Qwen3-32B定制个人天气查询插件
  • 搜索框检验法:在亚马逊,为何模糊的品牌名会让算法“听不懂”你的订单
  • 2026杭州行业知名二手自行车怎么选购,口碑好的二手自行车推荐 - myqiye
  • 惠普OMEN游戏本终极性能优化指南:OmenSuperHub开源工具深度解析
  • Phi-3-Mini-128K服务器运维实战:利用Linux命令进行模型服务监控与日志管理
  • ubuntun一句话脚本速成openclaw和ollama免费使用(未验证)
  • 外贸企业必看:中美空运公司哪家靠谱?实力企业推荐 - 品牌评测官