事务传播行为
前面已经讲解过事务的使用,但在一些场景下事务的使用会更加复杂。例如我们在处理一个业务时,该业务有几个部分组成,在执行中几个部分都完成了,但有一部分因为特殊原因没能够执行成功。按照事务的说法,要么全部成功,要么全部失败,所以在接下来的处理逻辑上,会因为一部分的失败,导致大部分的数据进行回滚。
显然这样不合理,在系统中可能会造成锁表,使系统卡死。我们的实际做法是保留成功的数据,然后回滚失败的部分,当然失败的那部分会进行后续的处理。这样的处理方式其实就是传播行为,通俗来说就是执行到某段代码时,对已存在事务采用不同处理方式。现在,来看在代码中定义的传播行为,代码如下所示。
package org.springframework.transaction.annotation;
public enum Propagation {
REQUIRED(0),
SUPPORTS(1),
MANDATORY(2),
REQUIRES_NEW(3),
NOT_SUPPORTED(4),
NEVER(5),
NESTED(6);
private final int value;
private Propagation(int value) {
this.value = value;
}
public int value() {
return this.value;
}
}
在上面的代码中,可以看到主要有七种事务传播行为。为了方便直观地说明,我们先假设一个批量处理是当前的执行交易,里面分几个小部分逻辑在执行,这里简化为一个,如图7.7所示。

Figure 1. 图7.7 事务示意图
我们先通过一段代码进行说明,方便理解上面描述的示意图,代码如下所示。
class ServiceA{
public void methodA(){
//按照事务的方式调用方法B
ServiceB.methodB();
}
}
class ServiceB{
public void methodB(){
//to do
}
}
下面我们通过表格展示传播行为及说明,如表7.6所示。

Figure 2. 表7.6 传播行为及说明
我们通过举例来加深对传播行为的理解,使用按照 A、B 来说明。假如传播行为是 REQUIRED,在使用 A 时,会调用 B。如果 A 已经开启了事务,在调用 B 时,B 将会运行在 A 的事务内部;如果 A 没有开启事务,将会给 B 分配一个事务。这样使用,在 A 或者 B 中只要出现异常,事务都会进行回滚,当然 B 也可能已经提交,但仍然会进行回滚。这也是默认的传播行为。
假设 A 的传播行为是 REQUIRED,B 的传播行为是 NEVER,那么在执行 B 时,就会抛出异常。