前言
上篇文章我们说过,Spring对事务的控制,是使用AOP切面实现的,我们使用时只需在方法上加上@Transactional注解,这时就有问题了。
1、A方法调用了B方法,两个方法都有事务,此时如果B方法异常,那么是让B方法提交,还是两个一起回滚。
2、A方法调用了B方法,但是只有A加了事务,此时是否将B也加入A的事务,如果B异常,是否回滚A。
3、A方法调用了B方法,两个方法都有事务,B正常执行完,但是A异常,此时是否回滚B的数据。
正文
Spring中定义的7种传播类型被定义成了枚举,在枚举类Propagation中定义。使用方式是指定注解的属性。
@Transactional(propagation=Propagation.REQUIRED)
1、REQUIRED
默认的事务传播级别,使用该级别的特点是,如果上下文中已经存在了事务,那么就加入到当前事务中执行,如果当前上下文中不存在事务,则新建事务执行。这个级别通常能满足大多数的业务场景。
比如:方法A调用方法B,B的事务级别是REQUIRED,由于A已经起了事务,此时调用B看到上下文中已经有了A的事务,就不再起新的事务。而A在执行时发现自己没有在事务中,就会为自己分配一个事务。这样,方法A或者方法B中任何地方出现异常,事务都会回滚,方法A和方法B都要回滚。
2、SUPPORTS
该事务级别特点是:如果上下文中存在事务,则加入事务,如果没有事务,则使用非事务的方式执行。使用场景较少。
3、MANDATORY
该事务级别特点是:要求上下文中必须存在事务,否则就会抛出异常。使用场景比如:一段代码不能单独被调用执行,但是一旦被调用,就必须有事务包含,否则跑异常。
4、REQUIRES_NEW
该传播级别的特点是:每次都会新建一个事务,并且将上下文中的事务挂起,执行完新建的事务后,再将上下文中的事务恢复并执行。
比如我们设计方法A的事务级别是REQUIRED,方法B的事务级别是REQUIRES_NEW,那么当B执行的时候,A所在的事务就会挂起,B会起一个新的事务,等B完成后,A事务解挂继续执行。那么,A和B分别在2个不同的事务,互不影响,A失败回滚不会影响B提交,B失败回滚不会影响A提交。
5、NOT_SUPPORTED
该传播级别不支持事务,特点就是如果上下文中存在事务,则挂起事务,执行当前逻辑,结束后恢复上下文中的事务。
6、NEVER
该传播级别要求上下文中不能存在事务,一旦有事务,就会抛出运行时异常。
7、NESTED
和REQUIRES_NEW相似,但又有不同。REQUIRES_NEW另起一个事务,是和它的父事务相互独立的。而NESTED的事务则是和它的父事务相关联的,它的提交要等父事务一起提交,如果父事务回滚,它也要回滚。
总结
Spring的七种事务传播机制要根据实际场景来指定。