Transactional失效场景

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); // 内部调用
    }
    @Transactional
    private void save(User user) {
        // 业务逻辑
    }
}

解决方法1 将事务方法移到另一个类中:

@Service
public class UserService {

    @Autowired
    private UserRepository userRepository;

    public void saveUser(User user) {
        userRepository.save(user);
    }
}

@Repository
public class UserRepository {

    @Transactional
    public void save(User user) {
        // 业务逻辑
    }
}

解决方法2 使用AopContext.currentProxy() 获取当前代理对象

@Service
public class UserService {

    public void saveUser(User user) {
        //使用AopContext.currentProxy() 获取当前代理对象
        ((UserService) AopContext.currentProxy()).save(user);
    }

    @Transactional
    public 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); // 重新抛出异常
    }
}
posted @ 2025-04-01 00:58  mikuc3c  阅读(51)  评论(0)    收藏  举报