跳至主要內容

Spring @Transactional 详解:何时使用、为什么使用、如何使用

DD编辑部原创Spring BootSpring Boot大约 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`    | 串行化,最高隔离级别              |

✅ 主要优点

  • 简单易用,支持声明式事务管理。
  • JPAHibernateSpring 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 方法。
上次编辑于:
贡献者: didi