Spring Cloud 事务管理避坑指南:@Transactional 的正确使用姿势​

在日常开发中,你是否遇到过这些场景?

  • 数据库操作明明抛了异常,数据却没回滚?
  • 微服务调用多个接口,部分成功部分失败,数据不一致?
  • 加了 @Transactional 注解,事务依然不生效?

这些问题往往源于对 @Transactional 注解的误解或使用不当。今天我们就来彻底拆解它在 Spring Cloud 环境下的核心逻辑。


一、@Transactional 基础认知

1. 本质作用
在 Spring 管理的 Bean 方法上添加 @Transactional,声明该方法需要​​事务管理​​:

  • 方法执行前开启事务
  • 成功执行后提交事务
  • 抛出未捕获异常时回滚事务

2. 核心代码示例

@Service
public class OrderService {

    @Autowired
    private OrderDao orderDao;

    // 声明事务:方法内所有数据库操作作为原子单元
    @Transactional
    public void createOrder(Order order) {
        orderDao.insert(order);       // 插入订单
        inventoryService.deductStock(); // 扣减库存(假设是另一个Service)
        // 若此处抛出RuntimeException,订单和库存操作一起回滚!
    }
}

二、分布式场景下的典型应用

✅ 场景1:单服务多数据源操作

@Transactional
public void transfer(Account from, Account to, BigDecimal amount) {
    accountDao.deduct(from, amount);  // 操作数据源A
    accountDao.add(to, amount);       // 操作数据源B
    // 需配合分布式事务管理器(如Atomikos)实现跨库事务
}

✅ 场景2:微服务间调用(需谨慎!)

@Transactional
public void createOrder(OrderDTO dto) {
    // 1. 本地订单库操作(可回滚)
    orderDao.save(dto);  

    // 2. 调用库存服务(远程RPC)
    Response stockResp = inventoryFeignClient.deduct(dto.getSkuId()); 
    
    // 问题:若此处库存服务失败,本地事务不会回滚!
    // 解决方案:引入最终一致性方案(如本地消息表、Seata AT模式)
}

📌 关键结论
@Transactional​默认只能管理本地事务​​,跨服务调用需结合分布式事务方案!


三、必须掌握的6大注意事项

1. 默认只回滚 RuntimeException

@Transactional
public void update() throws Exception {
    // 抛出受检异常不会触发回滚!
    throw new Exception("受检异常"); 
}

// 解决方案:指定回滚异常类型
@Transactional(rollbackFor = Exception.class)






次阅读

扫描下方二维码,关注公众号:程序进阶之路,实时获取更多优质文章推送。


扫码关注

评论