文章目录
一、外部方法调内部方法,外部有@Transactional,内部有@Transactional(propagation = Propagation.REQUIRES_NEW)
// 外部事务
@Transactional
public void outerMethod() {
innerMethod();
}
// 内部事务
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void innerMethod() {
}
-
场景1:内部事务抛出异常,外层不捕获
- 结果:内外事务均回滚。
-
场景2:内部事务抛出异常,外层捕获异常
- 结果:内部事务回滚,外层事务提交。
-
场景3:内部事务正常提交,外层事务后续抛出异常
- 结果:内部事务提交有效,外层事务回滚。
结论:
1.REQUIRES_NEW会新开启事务,外部事务异常不会影响内部事务的提交/回滚
2.REQUIRES_NEW的内部事务的异常,可能会影响外部事务的回滚
- 内部事务因异常回滚后,异常会传播到外层方法,导致外层事务也回滚
- 若外层方法通过try-catch捕获了内部方法抛出的异常,外层事务不会因内部事务的异常而回滚。此时,只有内部事务自身回滚。
二、外部方法调内部方法,外部有@Transactional,内部有@Transactional(propagation = Propagation.NESTED)
结论:
1.Propagation.NESTED会新开启事务,外部事务异常不会影响内部事务的提交/回滚
- 内部事务的提交需要等待外部事务最终提交,外部事务回滚会导致内部事务回滚。
- 内部事务可以独立回滚(回滚到保存点),但外部事务仍可继续执行。
2.Propagation.NESTED的内部事务的异常,可能会影响外部事务的回滚
- 如果内部事务的异常未被捕获:NESTED 事务回滚到保存点,同时异常会传播到外部事务,默认导致外部事务回滚
- 如果内部事务的异常被捕获:仅内部事务回滚到保存点,外部事务可继续执行。
机制:
传播行为 | 内部事务回滚 | 外部事务回滚 |
---|---|---|
REQUIRES_NEW | 仅回滚内部事务,不影响外部事务。 | 仅回滚外部事务,不影响内部事务。 |
NESTED | 回滚到保存点,不影响外部事务其他操作。 | 回滚整个事务(包括所有保存点后的操作)。 |
实际应用场景:
(1) REQUIRES_NEW 适用场景
需要完全独立的事务:
-
记录操作日志(即使主事务回滚,日志仍需保留)。
-
异步任务触发(如发送消息到消息队列)。
(2) NESTED 适用场景
需要部分操作可回滚:
-
订单创建成功后,扣减库存失败时仅回滚库存操作,保留订单记录。
-
批量处理数据时,允许单条记录失败回滚,其他记录继续处理。