spring事务默认仅对runtimeexception和error回滚,受检异常(如exception及其子类)需显式配置rollbackfor;若自定义异常继承exception则必须指定,继承runtimeexception则默认回滚;需确保异常真实抛出且未被吞没,并可配合norollbackfor精细控制。

Spring 事务默认只对 RuntimeException 和 Error 自动回滚,遇到 Exception 及其子类(比如自定义的受检异常)时,事务不会回滚——除非你用 rollbackFor 显式告诉 Spring 哪些异常该触发回滚。
确认异常类型是否属于受检异常
这是配置前最关键的一步。Spring 是否需要你写 rollbackFor,取决于你的异常是不是继承自 Exception 而非 RuntimeException:
- 如果自定义异常是
public class BizException extends Exception→ 属于受检异常 → 必须配置rollbackFor = BizException.class - 如果自定义异常是
public class BizRuntimeException extends RuntimeException→ 默认就会回滚 → 不必额外配置 - 直接抛
new Exception("xxx")或IOException等标准受检异常,同样需要rollbackFor
@Transactional 中正确声明 rollbackFor
在方法或类上添加注解,并通过 rollbackFor 指定具体异常类型:
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
- 单个异常:
@Transactional(rollbackFor = BizException.class) - 多个异常:
@Transactional(rollbackFor = {BizException.class, SQLException.class}) - 想让所有异常都回滚(常见做法):
@Transactional(rollbackFor = Exception.class)
注意:rollbackFor 接收的是 Class 类型,不是字符串;它匹配异常本身及其所有子类。
确保异常真正“冒泡”到事务切面
即使配置了 rollbackFor,以下情况仍会导致回滚失效:
- 方法内部
try-catch吞掉了异常,没重新抛出 - 捕获后抛出另一个未在
rollbackFor中声明的新异常(比如catch (BizException e) { throw new IllegalArgumentException(); }) - 方法是
private、final或者被本类内其他方法this.xxx()直接调用(绕过代理,事务不生效) - 异常被声明在
throws中但实际并未抛出(Spring 只响应真实抛出的异常)
配合 noRollbackFor 实现更精细控制
当某些异常业务上不算失败,你不希望它导致回滚,可用 noRollbackFor 排除:
@Transactional(rollbackFor = Exception.class, noRollbackFor = ValidationException.class)- 优先级高于
rollbackFor:若一个异常同时匹配两者,以noRollbackFor为准 - 适用于如参数校验失败、用户提示类异常等明确“可接受”的场景
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










