REQUIRED、REQUIRES_NEW、NESTED的区别
文档
- Spring事务传播行为的七种类型
- Transaction rolled back because it has been marked as rollback-only异常产生的原因
- REQUIRED、REQUIRES_NEW、NESTED的区别
三种Spring事务传播类型对比
事务传播类型 | 说明 |
---|---|
PROPAGATION_REQUIRED | 当前存在事务:加入当前事务; 当前不存在事务:创建一个新事务。 |
PROPAGATION_REQUIRES_NEW | 当前存在事务:挂起当前事务,创建一个新事务; 当前不存在事务:创建一个新事务。 |
PROPAGATION_NESTED | 当前存在事务:创建一个嵌套事务; 当前不存在事务:创建一个新事务。 |
事务提交、回滚对比
2:REQUIRED | 2:REQUIRES_NEW | 2:NESTED | |
---|---|---|---|
1:REQUIRED 1无异常 + 2异常 | [回滚,回滚] | [回滚,回滚] | [回滚,回滚] |
1:REQUIRED 1无异常 + 2异常,1捕获2异常 | [回滚,回滚] 异常1 | [提交,回滚] | [提交,回滚] |
1:REQUIRED 1异常 + 2无异常 | [回滚,回滚] | [回滚,提交] | [回滚,回滚] |
1:NO 1无异常 + 2异常 | [提交,回滚] | [提交,回滚] | [提交,回滚] |
- 第一列表示第一个方法事务类型,NO表示无事务
- 第一行表示第二个方法事务类型
- 第一个方法调用第二个方法,两个方法在不同的类,事务均可生效
- 1无异常 + 2异常,表示第一个方法无异常,第二个方法有异常
- [提交,回滚],表示第一个方法中的事务提交,第二个方法中事务回滚
- 异常1:
org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only
总结
- 如果当前无事务,则REQUIRED、REQUIRES_NEW、NESTED三种事务传播类型无区别,效果都是创建一个新事务
- 如果当前存在事务,REQUIRED表示加入当前事务。可以理解为整体(方法一和方法二)使用同一个事务标识,同时提交或回滚。即使方法一捕获了方法二的异常,但是方法二抛出了异常,整体事务被标记为回滚了,此时方法一虽然可以继续运行到结束,但最终也是事务回滚,并且会主动抛出异常。
- 如果当前存在事务,REQUIRES_NEW表示挂起当前事务,创建一个新事务。方法一与方法二使用不同的事务,互不影响。需要注意的是,如果方法二抛出异常,方法一并没有捕获,导致方法一也抛出异常,此时方法一的事务也会回滚。
- 如果当前存在事务,NESTED表示创建一个嵌套事务。嵌套事务可以理解为在事务中创建一个保存点(savepoint),两个方法用同一个事务,调用方法二时,创建一个保存点。方法二抛出异常,则事务内部回退到保存点,只是事务内部进行了部分回退,整体的事务此时并没有提交或回滚,如果方法一捕获了方法二的异常,则事务会提交,因为方法二已提前回退,所以方法二表现为回滚。需要注意的是,如果方法二抛出异常,方法一并没有捕获,导致方法一也抛出异常,此时事务会回滚。
REQUIRED示例
示例1:REQUIRED1无异常 + REQUIRED2异常
-
PropagationServiceAImpl.java
@Override @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class) public void requiredToRequired() { update1(); propagationServiceB.required(); }
-
PropagationServiceBImpl.java
@Override @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class) public void required() { update3(); int i = 1 / 0; }
-
此时,update1、update3均会回滚
示例2:REQUIRED1无异常 + REQUIRED2异常,REQUIRED1捕获REQUIRED2异常
-
PropagationServiceAImpl.java
@Override @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class) public void requiredToRequired1() { update1(); try { propagationServiceB.required(); } catch (Exception e) { e.printStackTrace(); } }
-
PropagationServiceBImpl.java
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class) public void required() { update3(); int i = 1 / 0; }
-
此时,update1、update3均会回滚,并且会抛出
org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only
异常
示例3:REQUIRED1异常 + REQUIRED2无异常
-
PropagationServiceAImpl.java
@Override @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class) public void requiredToRequired2() { update1(); propagationServiceB.required1(); int i = 1 / 0; }
-
PropagationServiceBImpl.java
@Override @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class) public void required1() { update3(); }
-
此时,update1、update3均会回滚
示例4:NO无异常 + REQUIRED异常
-
PropagationServiceAImpl.java
@Override public void noToRequired() { update1(); propagationServiceB.required(); }
-
PropagationServiceBImpl.java
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class) public void required() { update3(); int i = 1 / 0; }
-
此时,update1提交,update3回滚
REQUIRES_NEW示例
示例1:REQUIRED无异常 + REQUIRES_NEW异常
-
PropagationServiceAImpl.java
@Override @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class) public void requiredToRequiresNew() { update1(); propagationServiceB.requiresNew(); }
-
PropagationServiceBImpl.java
@Override @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class) public void requiresNew() { update3(); int i = 1 / 0; }
-
此时,update1、update3均会回滚
示例2:REQUIRED无异常 + REQUIRES_NEW异常,REQUIRED捕获REQUIRES_NEW异常
-
PropagationServiceAImpl.java
@Override @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class) public void requiredToRequiresNew1() { update1(); try { propagationServiceB.requiresNew(); } catch (Exception e) { e.printStackTrace(); } }
-
PropagationServiceBImpl.java
@Override @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class) public void requiresNew() { update3(); int i = 1 / 0; }
-
此时,update1会提交,update3会回滚
示例3:REQUIRED异常 + REQUIRES_NEW无异常
-
PropagationServiceAImpl.java
@Override @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class) public void requiredToRequiresNew2() { update1(); propagationServiceB.requiresNew1(); int i = 1 / 0; }
-
PropagationServiceBImpl.java
@Override @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class) public void requiresNew1() { update3(); }
-
此时,update1会回滚、update3会提交
示例4:NO无异常 + REQUIRES_NEW异常
-
PropagationServiceAImpl.java
@Override public void noToRequiresNew() { update1(); propagationServiceB.requiresNew(); }
-
PropagationServiceBImpl.java
@Override @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class) public void requiresNew() { update3(); int i = 1 / 0; }
-
此时,update1会提交,update3会回滚
NESTED示例
示例1:REQUIRED无异常 + NESTED异常
-
PropagationServiceAImpl.java
@Override @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class) public void requiredToNested() { update1(); propagationServiceB.nested(); }
-
PropagationServiceBImpl.java
@Override @Transactional(propagation = Propagation.NESTED, rollbackFor = Exception.class) public void nested() { update3(); int i = 1 / 0; }
-
此时update1、update3均会回滚
示例2:REQUIRED无异常 + NESTED异常,REQUIRED捕获NESTED异常
-
PropagationServiceAImpl.java
@Override @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class) public void requiredToNested1() { update1(); try { propagationServiceB.nested(); } catch (Exception e) { e.printStackTrace(); } }
-
PropagationServiceBImpl.java
@Override @Transactional(propagation = Propagation.NESTED, rollbackFor = Exception.class) public void nested() { update3(); int i = 1 / 0; }
-
此时,update1会提交,update3会回滚
示例3:REQUIRED异常 + NESTED无异常
-
PropagationServiceAImpl.java
@Override @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class) public void requiredToNested2() { update1(); propagationServiceB.nested1(); int i = 1 / 0; }
-
PropagationServiceBImpl.java
@Override @Transactional(propagation = Propagation.NESTED, rollbackFor = Exception.class) public void nested1() { update3(); }
-
此时,update1、update3均会回滚
示例4:NO无异常 + NESTED异常
-
PropagationServiceAImpl.java
@Override public void noToNested() { update1(); propagationServiceB.nested(); }
-
PropagationServiceBImpl.java
@Override @Transactional(propagation = Propagation.NESTED, rollbackFor = Exception.class) public void nested() { update3(); int i = 1 / 0; }
-
此时,update1会提交,update3会回滚