Spring Boot 事务失效场景

返回 面试 · 速查全集 SpringBoot常见面试题

@Transactional 基于 Spring AOP 代理;以下场景事务不生效或不符合预期。完整传播行为见 事务管理


速查表

#场景原因解决
1同类内部自调用绕过代理,AOP 不拦截注入自身代理、拆 Bean、AopContext.currentProxy()
2方法 非 public默认只代理 public改为 public 或 AspectJ 织入
3异常被 catch 未抛出代理认为方法成功重新抛出或 setRollbackOnly()
4受检异常默认不回滚默认只回滚 RuntimeExceptionrollbackFor = Exception.class
5类未被 Spring 管理无代理对象@Service / @Component
6数据库/引擎不支持MyISAM 等改用 InnoDB
7多数据源未指定事务绑错 Connection@Transactional + 正确 TransactionManager

1. 同类内部调用(最高频)

@Service
public class OrderService {
 
    @Transactional
    public void createOrder(Order order) {
        orderRepo.save(order);
        sendNotification(order);  // ❌ 直接调用,不走代理
    }
 
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void sendNotification(Order order) { /* ... */ }
}

正确做法

@Autowired
private OrderService self;  // 注入的是代理
 
public void createOrder(Order order) {
    orderRepo.save(order);
    self.sendNotification(order);  // ✅
}

或拆到 NotificationService 独立 Bean。


2. 方法非 public

@Transactional
protected void update() { }  // ❌ 无效

3. 异常被吞

@Transactional
public void process() {
    try {
        risky();
    } catch (Exception e) {
        log.error("fail", e);  // ❌ 未抛出,不回滚
    }
}

4. 受检异常不回滚

@Transactional  // 默认不回滚 IOException
public void export() throws IOException { ... }
 
@Transactional(rollbackFor = Exception.class)  // ✅
public void export() throws IOException { ... }

面试一句话

事务本质是 代理对象 在方法前后操作 Connection;任何绕过代理让代理以为成功的写法都会失效。


相关笔记