事务管理 (Transaction Management)
全面的事务支持是使用 Spring 框架最令人信服的原因之一。Spring 框架为事务管理提供了一致的抽象,带来了以下好处:
- 跨不同事务 API 的一致编程模型:例如 Java 事务 API (JTA)、JDBC、Hibernate 和 Java 持久化 API (JPA)。
- 支持声明式事务管理。
- 更简单的编程式事务管理 API:相比 JTA 等复杂的事务 API,其 编程式方式 更加简单易用。
- 与 Spring 数据访问抽象的卓越集成。
以下各节描述了 Spring 框架的事务功能和技术:
- Spring 框架事务支持模型的优势:描述了为什么你会选择使用 Spring 框架的事务抽象,而不是使用 EJB 容器管理事务 (CMT) 或选择通过专有 API 驱动事务。
- 理解 Spring 框架事务抽象:概述了核心类,并描述了如何配置和从各种源获取
DataSource实例。 - 同步资源与事务:描述了应用程序代码如何确保正确创建、重用和清理资源。
- 声明式事务管理:描述了对声明式事务管理的支持。
- 编程式事务管理:涵盖了对编程式(即显式编码)事务管理的支持。
- 事务边界事件:描述了如何在事务中使用应用程序事件。
本章还包括关于最佳实践、应用服务器集成 以及 常见问题的解决方案 的讨论。
补充教学
1. 为什么“一致性”如此重要?
在没有 Spring 之前,如果你从本地 JDBC 事务切换到分布式跨库事务(JTA),你需要重写大量的底层代码。JDBC 使用 connection.commit(),而 JTA 需要操作 UserTransaction。
Spring 的威力:它通过 PlatformTransactionManager(及其现代的响应式变体 ReactiveTransactionManager)将底层实现细节屏蔽。无论底层是单机还是分布式,你的业务代码通常只需要一个简单的 @Transactional 注解。这种“一次编写,到处运行”的特性极大地降低了系统架构演进的成本。
2. 声明式 vs 编程式:核心权衡
- 声明式事务(主流推荐):通过 AOP 实现,对业务代码几乎零入侵。它非常适合大部分遵循“成功提交,异常回滚”规则的业务场景。
- 编程式事务(特殊场景):当你需要对事务边界进行极其细腻的控制(例如在长任务中只针对某一段代码开启独立事务),或者你的业务逻辑涉及到非常复杂的手动回滚决策时,编程式事务(如
TransactionTemplate)会更加直接。
3. 注意事务的“幻觉”
虽然 @Transactional 让事务变得异常简单,但如果不了解其背后的代理机制,很容易踩坑。常见的“失效”场景包括:
- 同类方法自调用:一个没有注解的方法调用同一个类中带
@Transactional的方法,事务不会生效。 - 异常被静默处理:如果你在业务逻辑里
try-catch了异常且没有重新抛出,Spring 将无法得知需要回滚。
4. 预览:我们将深入讨论什么?
在本章后续内容中,我们将深入拆解以下三个事务核心属性:
- 传播行为 (Propagation):当一个事务方法调用另一个事务方法时,该怎么办?(如
REQUIREDvsREQUIRES_NEW) - 隔离级别 (Isolation):如何平衡外部并发访问与数据一致性?(脏读、不可重复读、幻读)
- 回滚规则:哪些异常应该回滚?哪些不应该?