Java事务核心在于匹配传播行为、隔离级别与回滚策略:REQUIRED默认共用事务,REQUIRES_NEW新建独立事务,SUPPORTS有则用无则非事务,NEVER禁止事务内执行;隔离级别优先数据库默认配置,回滚需显式指定checked异常类型,避免自调用、非public方法等导致事务失效。

Java 事务的核心在于“一致性控制”,不是堆砌注解或配置,而是理解传播行为、隔离级别、回滚机制与实际场景的匹配。配得对,事务才真正生效;配错了,可能掩盖异常、导致数据不一致,甚至锁表。
传播行为怎么选?看调用关系
@Transactional 的 propagation 属性决定方法是否参与已有事务,或新建一个。常见组合:
- REQUIRED(默认):有事务就加入,没事务就新建。适用于大多数业务方法,比如下单时扣库存+写订单,必须同事务。
- REQUIRES_NEW:总是挂起当前事务,新建独立事务。适合日志记录、异步通知等“事后动作”,避免主事务失败导致日志丢失。
- SUPPORTS:有就用,无就不走事务。适合只读查询,但注意:它不保证隔离性,也不触发事务管理器拦截。
- NEVER:明确禁止在事务内执行。可用于校验工具类,一旦检测到事务上下文立即抛异常,防止误嵌套。
隔离级别设多高?看并发冲突概率
数据库默认隔离级别(如 MySQL 是 REPEATABLE READ)通常够用。Java 层设置需谨慎:
- READ_COMMITTED:防脏读,适合高并发更新场景(如抢券),避免幻读靠应用层加锁或版本号。
- REPEATABLE_READ:MySQL 默认,防脏读+不可重复读,但幻读仍可能(需间隙锁或 select for update)。
- SERIALIZABLE:全串行,性能差,极少用。除非金融级强一致性要求,且已评估吞吐影响。
- 不建议在 @Transactional 上硬编码 isolation 属性,优先由数据库统一配置,Java 层聚焦业务逻辑控制。
回滚规则怎么定?别只靠 RuntimeException
Spring 默认只对 unchecked 异常(RuntimeException 及其子类)回滚。常见误区:
立即学习“Java免费学习笔记(深入)”;
- 捕获了异常却没抛出 → 事务不回滚。正确做法:要么不 catch,要么 catch 后 throw new RuntimeException(e)。
- 想对 checked 异常回滚 → 显式声明:
@Transactional(rollbackFor = IOException.class)。 - 部分操作不希望回滚(如发短信失败不影响订单创建)→ 拆方法 + REQUIRES_NEW,或用 try-catch 包裹并记录错误日志。
事务失效的典型场景,检查这几点
加了 @Transactional 却没生效?先排查:
- 方法不是 public(代理机制限制);
- 自调用:同一个类里 A 方法调 B 方法,B 有 @Transactional → 不生效(代理对象未介入);
- 没有启用事务管理:忘了
@EnableTransactionManagement或 XML 中没配<annotation-driven></annotation-driven>; - 使用了非事务性数据源(如 H2 内存库未开启事务支持,或 JdbcTemplate 绑定的 DataSource 未被事务管理器管理);
- 异步方法(@Async)默认脱离事务上下文,需手动传播或改用 TransactionTemplate。


















