@Transactional 是 Spring 声明式事务核心注解,通过 AOP 代理在 public 方法执行前后织入事务逻辑,支持传播行为、隔离级别等属性配置,但存在自调用、非 public 方法、异常捕获等导致失效的常见场景。

@Transactional 是 Spring 提供的声明式事务管理核心注解,用在方法或类上,让 Spring 自动帮你开启、提交或回滚数据库操作。它不直接操作数据库,而是通过 AOP 在方法执行前后织入事务逻辑。
用在方法上最常见
通常加在 Service 层的 public 方法上,Spring 会为该方法创建代理,在调用前开启事务,成功时提交,抛出未捕获的运行时异常(RuntimeException 及其子类)时回滚。
- 必须是 public 方法,private/protected 方法加了也无效(代理机制限制)
- 同一类中方法 A 调用本类的 @Transactional 方法 B,B 的事务不会生效(内部调用绕过代理)
- 默认只对 RuntimeException 和 Error 回滚;若想对 checked 异常(如 Exception)也回滚,要显式写 @Transactional(rollbackFor = Exception.class)
常用属性控制行为
事务不是“开就完事”,经常需要微调:
- propagation:传播行为,比如 REQUIRES_NEW 表示新建事务(挂起当前事务),SUPPORTS 表示支持当前事务但无事务也能运行
- isolation:隔离级别,如 ISOLATION_READ_COMMITTED(避免脏读),多数场景用默认即可
- timeout:超时时间(秒),防止事务长时间占用资源
- readOnly:设为 true 可提升查询性能(部分数据库会优化),且 Spring 会阻止 insert/update/delete 操作
类上使用要小心
加在类上,表示该类所有 public 方法都启用事务(等价于每个方法都加)。但要注意:
立即学习“Java免费学习笔记(深入)”;
- 无法为不同方法设置不同传播行为或回滚规则,灵活性低
- 如果类里有不需要事务的方法,反而增加了不必要的代理开销
- 推荐按需加在具体方法上,更清晰、更可控
事务失效的典型情况
写了 @Transactional 却没生效?常见原因有:
- 方法不是 public(private、package-private、protected 都不行)
- 自调用:A 方法调用本类的 B 方法(B 有 @Transactional),因未走代理,事务不触发
- 异常被 try-catch 吞掉且没重新抛出,Spring 捕获不到异常,就不会回滚
- 数据源没配置事务管理器(PlatformTransactionManager),或没开启 @EnableTransactionManagement


















