java 技术随笔

Spring Boot 事务管理:@Transactional 用法、回滚规则与常见坑

Spring 通过 @Transactional 声明式事务管理,让方法要么全部成功、要么整体回滚,避免“扣了钱没下单”这类半成品数据。下面以 Spring Boot + MyBatis 为例说明用法与坑点。

一、基础用法

@Service
public class OrderService {
    @Autowired
    private OrderMapper orderMapper;

    @Transactional
    public void createOrder(Order order) {
        orderMapper.insert(order);
        // 若下面抛异常,上面的 insert 会回滚
        int i = 1 / 0;
    }
}

二、回滚规则

  • 默认只在运行时异常(RuntimeException) 和 Error 时回滚;受检异常(checked exception)不会回滚。
  • 要让所有异常都回滚,显式声明:@Transactional(rollbackFor = Exception.class)
  • 手动回滚:在 catch 中调用 TransactionAspectSupport.currentTransactionStatus().setRollbackOnly()

三、传播行为(Propagation)

传播行为说明
REQUIRED(默认)有事务则加入,没有则新建
REQUIRES_NEW挂起当前事务,新建独立事务
NESTED在当前事务内嵌一个子事务,可单独回滚
SUPPORTS / NOT_SUPPORTED / NEVER分别按需“支持/不支持/禁止”事务

四、常见坑点

  1. 自调用失效:同一个类里 A 方法调用带 @Transactional 的 B 方法,事务不生效(代理未介入),应拆到不同 Bean。
  2. 注解加在私有方法或内部调用上无效;应加在 public 方法上。
  3. 数据库引擎不支持事务:MySQL 的 MyISAM 不支持事务,需用 InnoDB。
  4. 事务范围过大:长事务占用连接、易锁等待,只把必要的写操作放进事务。
  5. 异常被 catch 吞掉且不手动回滚,事务会“以为成功”而提交。
标签
Spring Boot事务