Spring @Transactional 详解:何时使用、为什么使用、如何使用
原创大约 3 分钟
Spring @Transactional 详解:何时使用、为什么使用、如何使用
本文是关于 Spring Framework 中 @Transactional
注解的完整教程,面向有一定基础的开发者,将详细介绍注解功能、使用场景、核心特性、优缺点,并配有清晰的图表说明。
@Transactional
是什么?
✅ @Transactional
是 Spring 提供的事务注解,用于声明式事务管理。它可以确保被标记的方法(或代码块)运行在数据库事务环境中。
🛠️ 什么时候使用
以下场景建议使用 @Transactional
:
当你需要执行多个数据库操作,且这些操作必须具备原子性(要么全部成功,要么全部失败)。
- 需要在出现错误或异常时自动回滚操作。
- 希望避免手动管理事务(比如直接使用 JDBC 或 EntityManager 的事务 API)。
@Transactional
的核心特性
⚙️ | 核心特性 | 功能说明 |
| --------------- | ------------------------------------------------------------------------- |
| **原子性** | 事务内的所有操作要么全部成功,要么全部失败回滚。 |
| **自动回滚** | 遇到 `RuntimeException` 和 `Error` 时会自动回滚事务。 |
| **事务传播** | 定义当前方法调用其他事务方法时的事务传播行为。 |
| **隔离级别** | 通过设置不同的隔离级别来解决并发访问问题。 |
| **只读优化** | 针对只读事务进行性能优化。 |
🔁 事务传播机制(常用类型)
| 传播类型 | 行为描述 |
| ---------------- | ------------------------------------------- |
| `REQUIRED` | 有事务就加入,没有就新建(默认行为) |
| `REQUIRES_NEW` | 总是新建事务,挂起当前事务 |
| `NESTED` | 在当前事务内创建嵌套事务 |
| `MANDATORY` | 必须在已存在的事务中运行,否则抛出异常 |
🔒 事务隔离级别
| 隔离级别 | 说明 |
| ----------------- | --------------------------------- |
| `DEFAULT` | 使用数据库默认的隔离级别 |
| `READ_COMMITTED` | 读已提交,避免脏读 |
| `REPEATABLE_READ` | 可重复读,避免脏读和不可重复读 |
| `SERIALIZABLE` | 串行化,最高隔离级别 |
✅ 主要优点
- 简单易用,支持声明式事务管理。
- 与 JPA、Hibernate、Spring Data 等框架完美集成。
- 异常时自动回滚,无需手动处理。
- 减少样板代码,提高开发效率。
- 支持嵌套事务等高级特性。
❌ 使用限制
- 使用不当容易踩坑,需要充分理解其原理。
- 基于代理实现:对
private
方法和同类内部调用无效。 - 默认只对运行时异常回滚,检查异常需要额外配置。
- 复杂的嵌套调用中排查回滚原因比较困难。
📦 代码示例
@Service
public class PaymentService {
@Transactional
public void makePayment(Order order) {
debitAccount(order);
updateInventory(order);
saveOrder(order);
// 如果抛出 RuntimeException,事务会自动回滚
}
}
🔁 自定义回滚配置
@Transactional(rollbackFor = Exception.class)
📉 不使用事务的风险
- 部分数据库操作成功,部分失败。
- 导致数据不一致问题。
🧪 最佳实践
- 建议在Service 层的公共方法上使用。
- 避免在 Controller 层或 DAO 层使用
@Transactional
。 - 注意代理失效问题:不要在同一个类内部调用
@Transactional
方法。