5 Transactional失效场景
1 方法非 public
修饰
原因
Spring 的 @Transactional 注解只能作用于 public 方法。如果方法是非 public 的(如 private、protected 或包级私有),事务不会生效。
@Transactional
private void saveUser(User user) {// 业务逻辑
}//改为public修饰
@Transactional
public void saveUser(User user) {// 业务逻辑
}
2 类内部方法调用。
原因
Spring 的事务管理是基于代理模式实现的。如果通过类内部方法调用事务方法,代理不会生效,事务也不会生效。
场景:
@Service
public class UserService {public void saveUser(User user) {save(user); // 内部调用}@Transactionalprivate void save(User user) {// 业务逻辑}
}
解决方法1 将事务方法移到另一个类中:
@Service
public class UserService {@Autowiredprivate UserRepository userRepository;public void saveUser(User user) {userRepository.save(user);}
}@Repository
public class UserRepository {@Transactionalpublic void save(User user) {// 业务逻辑}
}
解决方法2 使用AopContext.currentProxy() 获取当前代理对象
@Service
public class UserService {public void saveUser(User user) {//使用AopContext.currentProxy() 获取当前代理对象((UserService) AopContext.currentProxy()).save(user);}@Transactionalpublic void save(User user) {// 业务逻辑}
}
3 异常未抛出或被捕获。
原因:
默认情况下,@Transactional 只在抛出 RuntimeException 或 Error 时回滚事务。如果异常被捕获且未重新抛出,事务不会回滚。
@Transactional
public void saveUser(User user) {try {// 业务逻辑} catch (Exception e) {// 捕获异常}
}
解决方法
@Transactional
public void saveUser(User user) {try {// 业务逻辑} catch (Exception e) {throw new RuntimeException(e); // 重新抛出异常}
}