Skip to content
极高进阶

一句话答案

7 种传播行为核心三个:REQUIRED(有则加入无则新建)、REQUIRES_NEW(总是新建)、NESTED(嵌套事务/保存点)。

核心要点

7 种事务传播行为(propagation):

传播行为含义
REQUIRED(默认)有事务则加入,没有则新建(最常用)
REQUIRES_NEW无论如何都新建事务,挂起当前事务(独立事务,互不影响)
SUPPORTS有事务则加入,没有则以非事务方式执行
NOT_SUPPORTED以非事务方式执行,有事务则挂起
MANDATORY必须在事务内执行,没有事务则抛异常
NEVER不能在事务内执行,有事务则抛异常
NESTED有事务则在当前事务内创建嵌套事务(savepoint),没有则新建

实际常用场景:

java
// REQUIRED:默认,外层事务回滚,内层也回滚
@Transactional(propagation = Propagation.REQUIRED)

// REQUIRES_NEW:日志记录,即使主业务回滚,日志也要保存
@Transactional(propagation = Propagation.REQUIRES_NEW)

// NESTED:子事务失败只回滚到 savepoint,不影响外层
@Transactional(propagation = Propagation.NESTED)

事务失效的 8 种常见场景:

1. 方法不是 public 的

java
@Transactional
private void doSomething() { ... }  // ❌ 事务失效,只有 public 方法才能被代理拦截

2. 自调用(同类内方法调用)

java
@Service
class OrderService {
    public void placeOrder() {
        this.doCreate();  // ❌ this 调用的是原始对象,不是代理对象,事务不生效
    }
    
    @Transactional
    public void doCreate() { ... }
}
// 解决:注入自身代理,或拆分到不同类

3. 异常被吞掉(catch 了但没重新抛出)

java
@Transactional
public void doSomething() {
    try {
        // 业务逻辑
    } catch (Exception e) {
        log.error("error", e);  // ❌ 异常被捕获,Spring 不知道出了问题,不会回滚
    }
}

4. 抛出的异常类型不对

java
@Transactional  // 默认只回滚 RuntimeException 和 Error
public void doSomething() throws Exception {
    throw new Exception("checked");  // ❌ 受检异常不触发回滚
}
// 解决:@Transactional(rollbackFor = Exception.class)

5. 多线程调用(事务只在当前线程有效)

java
@Transactional
public void doSomething() {
    new Thread(() -> updateDB()).start();  // ❌ 新线程有新的数据库连接,不在同一事务中
}

6. 数据库或表不支持事务

  • MyISAM 引擎不支持事务,只有 InnoDB 支持

7. Bean 没有被 Spring 管理

java
class OrderService {  // ❌ 没有 @Service,不是 Spring Bean,AOP 代理不会生成
    @Transactional
    public void doSomething() { ... }
}

8. 传播行为配置错误

java
@Transactional(propagation = Propagation.NOT_SUPPORTED)
// 明确配置了以非事务方式执行,事务失效
追问与易错

追问方向:

  • REQUIRED 和 REQUIRES_NEW 区别?
  • NESTED 和 REQUIRES_NEW 区别?
  • 什么场景用 REQUIRES_NEW?

易错点:

  • ❌ 事务传播就是事务嵌套——只有 NESTED 是嵌套
  • ❌ REQUIRES_NEW 子事务回滚影响外层——不会

💡 记忆锚点

传播行为记三个就够:REQUIRED(有车搭车没车打车=默认)、REQUIRES_NEW(不管有没有车都自己打车=独立事务,如记日志)、NESTED(坐车但系安全带=savepoint,子回滚不影响主)。事务失效八大坑:非public/自调用/catch吞异常/checked异常/多线程/MyISAM/非Spring Bean/传播配错。