一句话总结
Spring事务传播机制定义了事务方法间相互调用时的行为,共7种。最常用的是REQUIRED(加入现有事务)、REQUIRES_NEW(新建事务)、NESTED(嵌套事务)。
初级理解
七种传播行为:
1. REQUIRED(默认):有事务则加入,无则新建
2. REQUIRES_NEW:无论是否有事务,都新建事务,挂起当前事务
3. SUPPORTS:有事务则加入,无则以非事务方式执行
4. NOT_SUPPORTED:以非事务方式执行,挂起当前事务
5. MANDATORY:必须在事务中调用,否则抛异常
6. NEVER:以非事务方式执行,若在事务中则抛异常
7. NESTED:有事务则在嵌套事务中执行(Savepoint),无则新建
一句话总结:REQUIRED加入现有事务,REQUIRES_NEW新建事务,NESTED嵌套事务。
中级深入
REQUIRED vs REQUIRES_NEW vs NESTED:
REQUIRED:加入现有事务(最常用)
REQUIRES_NEW:新建事务,挂起当前事务(独立事务)
NESTED:嵌套事务,使用Savepoint(外层回滚则内层也回滚)
// 例子
@Transactional
public void methodA() {
methodB(); // REQUIRED: 加入外层事务
methodC(); // REQUIRES_NEW: 新建独立事务
methodD(); // NESTED: 嵌套事务
}
注意:REQUIRES_NEW会挂起当前事务,如果外层事务回滚,内层已提交的事务不会回滚。
高级拓展
NESTED与REQUIRES_NEW的区别:
• REQUIRES_NEW:完全独立的事务,与外层事务无关
• NESTED:嵌套事务,基于Savepoint,外层回滚则内层也回滚
// NESTED示例
@Transactional
public void methodA() {
try {
methodB(); // 嵌套事务
} catch (Exception e) {
// 嵌套事务回滚,外层事务可以选择继续
}
methodC(); // 外层事务继续
}
面试加分项:能说出REQUIRED/REQUIRES_NEW/NESTED的区别、Savepoint机制,说明你对Spring事务有深入理解。
实战场景
场景:日志记录不影响主事务
@Service
public class OrderService {
@Autowired
private LogService logService;
@Transactional
public void createOrder(OrderDTO order) {
orderMapper.insert(order);
// 日志记录使用独立事务,即使日志失败也不影响订单创建
logService.log("创建订单: " + order.getOrderNo());
}
}
@Service
public class LogService {
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void log(String message) {
logMapper.insert(new Log(message));
}
}
面试模拟
Q:REQUIRED和REQUIRES_NEW的区别?
A:REQUIRED会加入现有事务,如果当前没有事务则新建;REQUIRES_NEW无论是否存在事务,都会新建事务,并挂起当前事务。例如方法A调用方法B,如果B是REQUIRED,则B加入A的事务;如果B是REQUIRES_NEW,则B新建事务,A的事务被挂起。
Q:NESTED和REQUIRES_NEW的区别?
A:REQUIRES_NEW是完全独立的事务,与外层事务无关;NESTED是嵌套事务,基于Savepoint,外层回滚则内层也回滚。REQUIRES_NEW适合日志记录等需要独立事务的场景,NESTED适合需要部分回滚的场景。