Spring事务-事务传播级别

事务是逻辑处理原子性的保证手段,通过使用事务控制,可以极大的避免出现逻辑处理失败导致的脏数据等问题。
事务最重要的两个特性,是事务的传播级别和数据隔离级别。传播级别定义的是事务的控制范围,事务隔离级别定义的是事务在数据库读写方面的控制范围。

在spring中我们对事务的定义主要是通过注解@Transactional,控制传播级别的就是参数propagation是一个Propagation的枚举有如下的值

REQUIRED(PROPAGATION_REQUIRED)

默认的spring事务传播级别,使用该级别的特点是,如果上下文中已经存在事务,那么就加入到事务中执行,如果当前上下文中不存在事务,则新建事务执行。所以这个级别通常能满足处理大多数的业务场景。

即,当前的事务如果没有运行在@Transactional注解的方法中,新建一个事务,如果运行在一个@Transactional注解的方法中则加入当前事务,一旦出现异常,会连调用者的事务一起回滚。

SUPPORTS(PROPAGATION_SUPPORTS)

从字面意思就知道,supports,支持,该传播级别的特点是,如果上下文存在事务,则支持事务加入事务,如果没有事务,则使用非事务的方式执行。所以说,并非所有的包在transactionTemplate.execute中的代码都会有事务支持。这个通常是用来处理那些并非原子性的非核心业务逻辑操作。应用场景较少。

即,当前的事务如果没有运行在@Transactional注解的方法中,则没有事务,如果运行在一个@Transactional注解的方法中则加入当前事务,一旦出现异常,会连调用者的事务一起回滚。

MANDATORY(PROPAGATION_MANDATORY)

该级别的事务要求上下文中必须要存在事务,否则就会抛出异常!配置该方式的传播级别是有效的控制上下文调用代码遗漏添加事务控制的保证手段。比如一段代码不能单独被调用执行,但是一旦被调用,就必须有事务包含的情况,就可以使用这个传播级别。

即,当前的方法必须运行在有@Transactional注解的方法种,否则会抛出异常,和NEVER相反。

REQUIRES_NEW(PROPAGATION_REQUIRES_NEW)

从字面即可知道,new,每次都要一个新事务,该传播级别的特点是,每次都会新建一个事务,并且同时将上下文中的事务挂起,执行当前新建事务完成以后,上下文事务恢复再执行。

即,当前的方法单独运行会以事务方式运行,在@Transactional注解的方法中运行,运行到该方法时候回将当前事务挂起,新建一个事务运行,一旦出现异常,只会回滚该方法的事务,不会回滚调用者的事务。

这是一个很有用的传播级别,举一个应用场景:现在有一个发送100个红包的操作,在发送之前,要做一些系统的初始化、验证、数据记录操作,然后发送100封红包,然后再记录发送日志,发送日志要求100%的准确,如果日志不准确,那么整个父事务逻辑需要回滚。
怎么处理整个业务需求呢?就是通过这个PROPAGATION_REQUIRES_NEW 级别的事务传播控制就可以完成。发送红包的子事务不会直接影响到父事务的提交和回滚。

NOT_SUPPORTED(PROPAGATION_NOT_SUPPORTED)

这个也可以从字面得知,not supported ,不支持,当前级别的特点就是上下文中存在事务,则挂起事务,执行当前逻辑,结束后恢复上下文的事务。

即,当前方法单独运行不会以事务方法运行,如果运行在在@Transactional注解的方法中,运行到该方法时候会将当前事务挂起,以非事务的方式执行该方法在恢复事务

这个级别有什么好处?可以帮助你将事务极可能的缩小。我们知道一个事务越大,它存在的风险也就越多。所以在处理事务的过程中,要保证尽可能的缩小范围。比如一段代码,是每次逻辑操作都必须调用的,比如循环1000次的某个非核心业务逻辑操作。这样的代码如果包在事务中,势必造成事务太大,导致出现一些难以考虑周全的异常情况。所以这个事务这个级别的传播级别就派上用场了。用当前级别的事务模板抱起来就可以了。

NEVER(PROPAGATION_NEVER)

该事务更严格,上面一个事务传播级别只是不支持而已,有事务就挂起,而PROPAGATION_NEVER传播级别要求上下文中不能存在事务,一旦有事务,就抛出runtime异常,强制停止执行!这个级别上辈子跟事务有仇。

即,该方法不能运行在注解@Transactional的方法中,和MANDATORY相反

NESTED(PROPAGATION_NESTED)

字面也可知道,nested,嵌套级别事务。该传播级别特征是,如果上下文中存在事务,则嵌套事务执行,如果不存在事务,则新建事务。

即:和REQUIRED(PROPAGATION_REQUIRED)类似,很少见

附录

测试代码见:https://gitee.com/liuhao163/test-transational