问题背景
在使用 Spring 框架进行数据库操作时,开发者通常会使用 @Transactional 注解来管理事务。其中,rollbackFor 属性用于指定哪些异常会触发事务回滚。但很多开发者发现即使设置了 rollbackFor = Exception.class,事务依然没有回滚。
常见原因
- 异常被捕获未抛出:如果方法内部用 try-catch 捕获了异常且未重新抛出,Spring 无法感知异常,不会触发回滚。
- 非 public 方法:Spring AOP 默认只代理 public 方法,若
@Transactional标注在 private、protected 或 package-private 方法上,事务将不生效。 - 自调用问题:同一个类中,一个方法调用另一个带
@Transactional的方法(如 this.method()),由于绕过了代理对象,事务不会生效。 - 异常类型不匹配:默认情况下,Spring 只对
RuntimeException和Error回滚。若抛出的是受检异常(checked exception)且未配置rollbackFor,也不会回滚。 - 数据源或事务管理器配置错误:未正确启用事务管理(如缺少
@EnableTransactionManagement)或使用了不支持事务的数据源。
解决方案
- 确保异常被抛出到事务代理层,不要在业务方法内静默处理。
- 将
@Transactional注解放在 public 方法上。 - 避免类内部自调用,可通过注入自身 Bean 的方式调用事务方法。
- 明确指定
rollbackFor = Exception.class以覆盖所有异常类型。 - 检查 Spring 配置,确保事务管理已启用且数据源支持事务。
示例代码
@Service
public class UserService {
@Transactional(rollbackFor = Exception.class)
public void updateUser(User user) throws Exception {
// 数据库操作
userRepository.update(user);
if (someCondition) {
throw new Exception("业务异常");
}
}
}
注意:该方法必须是 public,且异常需传播到 Spring 代理层。