关于Spring事务嵌套回滚的一些测试总结(精简)

目录

  • 前言
    • 场景前提
    • 场景一
    • 场景二
    • 场景三(一般不用)
    • 场景四

前言

这是我在spring事务中遇到关于事务嵌套问题的一些记录总结。

场景前提

测试数据库:sql server
A类的service A方法调用B类的service B方法;

ServiceA {
     void methodA() {
         ServiceB.methodB();
     }
}
ServiceB { 
     void methodB() {
     } 
}

注意:spring的@transactional只会对运行时异常捕获,并进行回滚,
若想所有异常都回滚,则使用@Transactional(rollbackFor = Exception.class)
默认事务传播行为:Propagation=PROPAGATION_REQUIRED


场景一

A,B都使用事务注解:@Transactional(rollbackFor = Exception.class),

测试条件 结果
B发生异常,A未catch A回滚,B回滚
B发生异常,Acatch了异常,记录日志,未抛出异常 A回滚,B回滚,但出现了异常(Transaction rolled back because it has been marked as rollback-only)
B发生异常,Acatch了异常,记录日志,抛出异常 A回滚,B回滚
B执行成功后,A发生异常 A回滚,B回滚

结论:A,B只要有一个发生异常,A和B都会回滚


场景二

A使用事务注解:@Transactional(rollbackFor = Exception.class),B不使用事务;

测试条件 结果
B发生异常,A未catch A回滚,B回滚
B发生异常,Acatch了异常,记录日志,未抛出异常 A,B都不回滚
B发生异常,Acatch了异常,记录日志,抛出异常 A回滚,B回滚
B执行成功后,A发生了异常 A回滚,B回滚

结论:只要A发生异常,A,B都回滚;B发生异常,若A catch了异常,但没有将异常抛出,则A,B都不回滚;除此之外,A,B都回滚


场景三(一般不用)

A不使用事务,B使用事务注解:@Transactional(rollbackFor = Exception.class)

测试条件 结果
B发生异常,A未catch A不回滚,B回滚
B发生异常,Acatch了异常,记录日志,未抛出异常 A不回滚,B回滚
B发生异常,Acatch了异常,记录日志,抛出异常 A不回滚,B回滚
B执行成功后,A发生了异常 A,B都不回滚

结论:无论AB是否发生异常,A都不回滚;只有B发生异常,B才会回滚


场景四

A使用默认事务注解:@Transactional(rollbackFor = Exception.class)
B使用新事务注解:@Transactional(propagation = Propagation.REQUIRES_NEW,rollbackFor = Exception.class)

测试条件 结果
B发生异常,A未catch A不回滚,B回滚
B发生异常,Acatch了异常,记录日志,未抛出异常 A不回滚,B回滚
B发生异常,Acatch了异常,记录日志,抛出异常 A回滚,B回滚
B执行成功后,A发生了异常 A回滚,B不回滚

结论:A发生异常,只有A回滚,B不回滚;B发生异常,只有B回滚,A不回滚

即:AB属于两个独立的事务,互不影响。


以上均为个人测试后得到的结论,若有错误,请不吝指教。


[参考]:浅析Spring事务传播行为和隔离级别

你可能感兴趣的:(spring)