Spring事务传播机制

115 阅读2分钟

「这是我参与2022首次更文挑战的第9天,活动详情查看:2022首次更文挑战

事务的传播行为:用来描述某个事务传播行为修饰的方法,在嵌套进另一个方法时事务是如何传播的。

7种事务传播行为

Springorg.springframework.transaction.TransactionDefinition 接口中规定了7种类型的事务传播行为。

事务传播行为说明
PROPAGATION_REQUIRED如果当前没有事务,就新建一个事务;如果当前存在事务,则加入到这个事务中。 (默认行为)
PROPAGATION_SUPPORTS支持当前事务,如果当前没有事务,则以非事务的方式执行
PROPAGATION_MANDATORY支持当前事务,如果当前没有事务,则抛出异常
PROPAGATION_REQUIRES_NEW创建新事务,如果当前存在事务,则把当前事务挂起
PROPAGATION_NOT_SUPPORTED以非事务的方式执行,如果当前存在事务,则把当前事务挂起
PROPAGATION_NEVER以非事务的方式执行,如果当前存在事务,则抛出异常
PROPAGATION_NESTED如果当前存在事务,则在嵌套事务中执行,如果当前没有事务,则执行PROPAGATION_REQUIRED类似的操作

PROPAGATION_REQUIRED

在外层方法开启 PROPAGATION_REQUIRED 事务传播机制时,内层方法不开启也能加入到事务管理中。(在同一个 bean 中和不同 bean 中的效果都是相同的)

伪代码:

/**
 * 添加用户
 */
@Override
public void addUser() {
    userDao.insertUser(new User("测试2",2,"男"));
    userDao.insertUser(new User("测试3",3,"男"));
    if (true){
        throw new RuntimeException("测试异常");
    }
}
/**
 * 添加商品
 */
@Override
public void addShop() {
    shopDao.insert(new Shop("测试商品1",new BigDecimal(1)));
   // shopDao.insert(new Shop("测试商品2",new BigDecimal(2)));
}
/**
 * 测试 默认事务传播
 */
@Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
@Override
public void test1() {
    this.addUser();
    this.addShop();
}

PROPAGATION_SUPPORTS

如果当前存在事务的话,就加入到当前事务中,如果不存在的话就以非事务方式执行。不管内外层方法是否在同一个 bean

PROPAGATION_REQUIRES_NEW

外层方法开不开启事务都可以,外层方法异常不影响内层事务提交,内层方法各自开启事务,在内层方法遇到异常时各自回滚。

伪代码:

A类

/**
 * 添加商品
 */
@Transactional(propagation = Propagation.REQUIRES_NEW,rollbackFor = Exception.class)
@Override
public void addShop() {
    shopDao.insert(new Shop("测试商品1",new BigDecimal(1)));
}

C类

/**
 * 添加用户
 */
@Transactional(propagation = Propagation.REQUIRES_NEW,rollbackFor = Exception.class)
@Override
public void addUser() {
    userDao.insertUser(new User("测试2",2,"男"));
    userDao.insertUser(new User("测试3",3,"男"));
    throw new RuntimeException("测试异常");
}

B类(业务调用)

@Autowired
private AService aService;
@Autowired
private CService cService;
/**
 * 测试 
 */
@Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
@Override
public void test1() {
    aService.addShop();
    cService.addUser();
    throw new RuntimeException("外层异常");
}

PROPAGATION_NOT_SUPPORTED

使用该事务传播行为的方法,如果是在内层方法中使用,需要注意的是内层方法需要与外层方法处于不同的 bean 中,否则该事务传播行为将失效。

PROPAGATION_NEVER

以非事务的方式执行,如果当前存在事务,则抛出异常。内外层方法在同一个 bean 中时无效。