在日常开发中,我们会经常看到如下代码

@Transactional
public void save(User user) {
    save(user);
    log.info("save user");
}

只需要一个@Transactional注解,就可以轻松开启事务,使用起来很简单

但是,你是否真的了解它

在一些复杂的业务场景中,@Transactional其实并不是最佳选择

Spring中的事务管理方式

Spring 提供两种主要的事务管理方式

方式使用形式常见常见
声明式事务管理 @Transactional使用注解在方法或类上标记简单的业务逻辑、标准的业务服务层
编程式事务 TransactionTemplate显示调用模板执行事务复杂逻辑、多事务组合、可控性强的场景

@Transactional注解

@Service
public class UserService {
​
    @Resource
    private UserMapper userMapper;
​
    @Transactional
    public void createUser(User user) {
        boolean result = userMapper.insert(user);
        // 模拟异常
        if (!result) {
            throw new RuntimeException("用户创建失败");
        }
    }
}
​

潜在问题

  • 内部方法调用无效
@Service
public class OrderService {
​
    public void outerMethod() {
        innerTransactionalMethod(); // 无效!
    }
​
    @Transactional
    public void innerTransactionalMethod() {
        // 事务不会生效
    }
}
​
  • 默认异常行为不直观
@Transactional
public void updateUser() throws IOException {
    userRepository.save(user);
    throw new IOException(); // 不会回滚!
}
​
  • 不适用于异步/多线程环境

    • 事务只对当前线程有效,线程池或异步任务中的事务不会自动传播。
  • 不适用于方法中含有远程调用的业务
@Transactional
public void updateUser() throws IOException {
    userRepository.save(user);
    // 远程调用消息服务
    messageApi.sendMessage(user); //远程调用不受事务控制,可能导致事务超时或数据不一致
}
​

TransactionTemplate 编程式事务管理

@Service
public class UserService {
​
    @Resource
    private TransactionTemplate transactionTemplate;
​
    @Resource
    private UserRepository userRepository;
​
    public void createUser(User user) {
        transactionTemplate.executeWithoutResult(status -> {
            try {
                userRepository.save(user);
                if (true) throw new RuntimeException("模拟异常");
            } catch (Exception e) {
                status.setRollbackOnly();
                throw e;
            }
        });
    }
}
​

TransactionTemplate 优势

  • 事务边界明确
  • 控制更细粒度
  • 无代理问题
  • 适用于嵌套事务和多线程环境

对比

特性@TransactionalTransactionTemplate
使用简便性⭐⭐⭐⭐⭐⭐⭐
灵活性⭐⭐⭐⭐⭐⭐⭐
异常控制⭐⭐(需配置)⭐⭐⭐⭐⭐(手动)
内部方法事务❌(无效)
代码清晰度⭐⭐⭐⭐⭐⭐⭐⭐
多线程支持✅(手动管理)

怎么选择?

使用 @Transactional 的场景

  • 简单业务逻辑
  • 控制流程较清晰
  • 能处理其局限性

使用 TransactionTemplate 的场景

  • 复杂事务逻辑
  • 多个事务组合或嵌套调用
  • 内部调用或异步任务
  • 对异常控制和事务边界要求更高
最后修改:2025 年 08 月 07 日
如果觉得我的文章对你有用,请随意赞赏