Spring事务传播机制
一、什么是事务传播机制
事务传播机制是当一个事务方法被另一个事务方法调用时,这个事务方法应该如何去执行,例如method1方法添加了事务,去调用了method2事务方法,那么method2是继续在method1的事务中执行,还是新开一个事务时执行,这就需要method2的事务传播机制来决定。
在Spring中。事务控制是基于AOP实现的,它给我们提供了一个注解@Transactional,所以在实际中我们只需要使用这个注解就行了。
二、为什么需要一个事务传播机制
在Spring中。我们不用去关心事务是什么时候开始、提交或者回滚的。但是在这其中会出现一些问题,比如在两个service中:
① service1的方法调用了service2的方法,这两个方法都有事务,这时如果service2的方法发生异常,是让service2提交还是两个方法一起回滚;
② service1的方法调用了service2的方法,但是只有service1的方法加了事务,这时是否将service2也加入到service1的事务中去,如果service2的方法发生异常,是否需要回滚service1;
③ service1的方法调用了service2的方法,这两个方法都有事务,service2的方法已经执行完毕,紧接着继续执行service1的后续代码,这时发生异常,是否需要回滚service2方法。
三、7种事务传播行为
在开始介绍之前,我们首先要明确一点,Spring是使用的AOP代理的事务控制,它是针对于接口和类的,如果在同一个service类中的两个方法相互调用,传播机制并不会生效。
传播行为 | 含义 |
PROPAGATION_REQUIRED | 这是默认的传播行为。表示当前方法必须运行在事务中,如果当前事务存在,就直接使用这个事务,否则,开启一个新的事务。简单地说就是,如果存在事务,就用该事务,否则就创建一个事务拿来用。 |
PROPAGATION_REQUIRED_NEW | 表示当前方法必须运行在自己的事务中,会启动一个新的事务,如果存在当前事务,在执行期间就会挂起当前事务。 |
PROPAGATION_SUPPORTED | 表示当前方法不需要事务上下文,但如果存在当前事务的话,那么就在这个事务中执行。简单地说,如果存在事务就用,不存在事务就非事务执行。 |
PROPAGATION_MANDATORY | 表示该方法必须在事务中运行,如果当前事务不存在,就直接抛异常。 |
PROPAGATION_NOT_SUPPORTED | 表示该方法不应该运行在事务中,如果存在当前事务,那么在方法运行期间,会直接挂起当前事务。 |
PROPAGATION_NEVER | 表示当前方法不应该运行在事务上下文中,如果当前有事务运行,会直接抛异常。 |
PROPAGATION_NESTED | 表示如果当前已存在一个事务,那么该方法会嵌套在事务中运行,嵌套的事务可以独立于当前事务单独提交或回滚;如果当前不存在事务,那么就与PROPAGATION_REQUIRED一样。 |
例子:
service1:
@Transactional(propagation = Propagation.REQUIRED) public void method1(){ System.out.println("111"); service2.method2(); int i = 1/0; //抛异常 System.out.println("333"); }
service2:
@Transactional(propagation = Propagation.REQUIRED) public void method2() { Money money = new Money(); money.setUserId(2); money.setMoney(300); userMapper.updateByUserId(money); }
单独调用method2方法时,因为当前上下文不存在事务,所以会开启一个新的事务。
调用method1方法时,因为当前上下文不存在事务,所以会开启一个新的事务。当执行到method2时,发现当前上下文有事务,因此就加入到当前事务中来。