Spring事务的隔离级别和传播行为
一、简述
Spring 在 TransactionDefinition 接口中规定了7种类型的事务传播行为。事务传播行为是 Spring 框架独有的事务增强特性,它不属于的事务实际提供方数据库行为。这是 Spring 提供的强大的工具箱,使用事务传播行为可以提供许多便利。但是人们对事务的误解也颇多,你一定也听过“service方法事务最好不要嵌套”的传言。要想正确的使用工具首先需要了解工具。本文对七种事务传播行为做详细介绍,内容主要代码示例的方式呈现。
二、基础概念
1️⃣什么是事务传播行为?
事务传播行为用来描述由某一个事务传播行为修饰的方法被嵌套进另一个方法时的事务如何传播。用伪代码说明:代码中methodA()嵌套调用了methodB(),methodB()的事务传播行为由@Transaction(Propagation=XXX)设置决定。这里需要注意的是methodA()并没有开启事务,某一个事务传播行为修饰的方法并不是必须要在开启事务的外围方法中调用。
2️⃣Spring中七种事务传播行为
三、代码验证
1️⃣首先在数据库中创建两张表:
user1:2️⃣然后编写相应的Bean和DAO层代码:
User1:3️⃣最后也是具体验证的代码由service层实现,下面分情况列举。
1.PROPAGATION_REQUIRED
为User1Service和User2Service相应方法加上Propagation.REQUIRED属性。
User1Service方法:1.1 场景一
此场景外围方法没有开启事务。
验证方法1:结论:通过这两个方法证明了在外围方法未开启事务的情况下Propagation.REQUIRED修饰的内部方法会新开启自己的事务,且开启的事务相互独立,互不干扰。
1.2 场景二
外围方法开启事务,这个是使用率比较高的场景。
验证方法1:结论:以上试验结果证明在外围方法开启事务的情况下Propagation.REQUIRED修饰的内部方法会加入到外围方法的事务中,所有Propagation.REQUIRED修饰的内部方法和外围方法均属于同一事务,只要一个方法回滚,整个事务均回滚。
2.PROPAGATION_REQUIRES_NEW
为User1Service和User2Service相应方法加上Propagation.REQUIRES_NEW属性。
User1Service方法:2.1 场景一
外围方法没有开启事务。
验证方法1:结论:通过这两个方法证明了在外围方法未开启事务的情况下Propagation.REQUIRES_NEW修饰的内部方法会新开启自己的事务,且开启的事务相互独立,互不干扰。
2.2 场景二
外围方法开启事务。
验证方法1:结论:在外围方法开启事务的情况下Propagation.REQUIRES_NEW修饰的内部方法依然会单独开启独立事务,且与外部方法事务也独立,内部方法之间、内部方法和外部方法事务均相互独立,互不干扰。
3.PROPAGATION_NESTED
3.1 场景一
此场景外围方法没有开启事务。
验证方法1:结论:通过这两个方法证明了在外围方法未开启事务的情况下Propagation.NESTED和Propagation.REQUIRED作用相同,修饰的内部方法都会新开启自己的事务,且开启的事务相互独立,互不干扰。
3.2 场景二
外围方法开启事务。
验证方法1:结论:以上试验结果证明在外围方法开启事务的情况下
Propagation.NESTED
修饰的内部方法属于外部事务的子事务,外围主事务回滚,子事务一定回滚,而内部子事务可以单独回滚而不影响外围主事务和其他子事务
- REQUIRED、REQUIRES_NEW、NESTED异同
由“1.2 场景二”和“3.2 场景二”对比,可知:
NESTED和REQUIRED修饰的内部方法都属于外围方法事务,如果外围方法抛出异常,这两种方法的事务都会被回滚。但是REQUIRED是加入外围方法事务,所以和外围事务同属于一个事务,一旦REQUIRED事务抛出异常被回滚,外围方法事务也将被回滚。而NESTED是外围方法的子事务,有单独的保存点,所以NESTED方法抛出异常被回滚,不会影响到外围方法的事务。
由“2.2 场景二”和“3.2 场景二”对比,可知:
NESTED和REQUIRES_NEW都可以做到内部方法事务回滚而不影响外围方法事务。但是因为NESTED是嵌套事务,所以外围方法回滚之后,作为外围方法事务的子事务也会被回滚。而REQUIRES_NEW是通过开启新的事务实现的,内部事务和外围事务是两个事务,外围事务回滚不会影响内部事务。
- 其他事务传播行为
不说了