@Transactional默认仅对RuntimeException及Error回滚,受检异常需用rollbackFor显式指定;noRollbackFor可排除特定异常不回滚,优先级高于rollbackFor;配置生效需满足public方法、外部Bean调用、异常未被吞没等前提。

在 Spring 的 @Transactional 注解中,默认只对 未检查异常(RuntimeException 及其子类)和 Error 自动回滚,对受检异常(如 Exception 及其子类,但不包括 RuntimeException)不会自动回滚。要自定义回滚规则,主要通过 rollbackFor 和 noRollbackFor 属性配置。
指定哪些异常触发回滚(rollbackFor)
当方法抛出指定的异常类型(包括其子类)时,事务将回滚:
- 支持类名、Class 对象或 Class 数组,例如:
rollbackFor = IOException.class或rollbackFor = {SQLException.class, CustomException.class} - 即使该异常是受检异常,只要显式声明,也会触发回滚
- 注意:若传入的是
RuntimeException类型,效果与默认行为一致,但可增强可读性
指定哪些异常不触发回滚(noRollbackFor)
用于排除某些本应导致回滚的异常,使其不触发回滚(事务继续提交):
- 常见于业务中明确“某种异常不算失败”的场景,例如:
noRollbackFor = ValidationException.class - 同样支持单个 Class 或 Class 数组
- 该设置优先级高于
rollbackFor;若某异常同时匹配两者,以noRollbackFor为准
注意事项与常见误区
配置生效需满足前提条件,否则规则无效:
-
@Transactional必须作用在 public 方法 上,且调用必须来自外部 Bean(非 this 调用) - 异常必须“抛出到事务切面能捕获的位置”——即不能在方法内
catch后吞掉,或重新包装为未声明的异常类型 - Spring 默认使用 JDK 动态代理或 CGLIB 代理,若目标方法被同一类内其他方法直接调用(this.method()),事务注解不生效
- 回滚仅针对数据库操作;若事务中已执行 HTTP 调用、文件写入等非事务性操作,它们不会自动撤销
示例写法
一个典型配置:
@Transactional(
rollbackFor = {SQLException.class, IOException.class},
noRollbackFor = BusinessException.class
)
表示:遇到 SQLException 或 IOException 回滚;即使抛出 BusinessException(它本身是 RuntimeException 子类),也不回滚。










