Spring一共提供了7种事务传播行为:
1、PROPAGATION_REQURED;
2、PROPAGATION_REQURED_NEW;
3、PROPAGATION_NESTED;
4、PROPAGATION_SUPPORTS;
5、PROPAGATION_NOT_SUPPORTS;
6、PROPAGATION_NEVER;
7、PROPAGATION_MANDATORY;
假设事务从方法A传播到方法B,用户需要面对方法B,问自己一个问题:方法A有事务吗?
(1)如果没有,就新建一个事务;如果有,就加入当前事务。这就是PROPAGATION_REQURED,它也是Spring提供的默认事务传播行为,适合绝大多数场景。
(2)如果没有,就新建一个事务;如果有,就将当前事务挂起。这就是PROPAGATION_REQURED_NEW,意思就是创建了一个新事务,它和原来的事务没有任何关系了。
(3)如果没有,就新建一个事务;如果有,就在当前事务中嵌套其他事务。这就是PROPAGATION_NESTED,也就是“嵌套事务”,所嵌套的子事务与主事务之间是有关联的(当主事务提交或回滚,子事务也会提交或回滚)。
(4)如果没有,就以非事务方式执行;如果有,就使用当前事务。这就是PROPAGATION_SUPPORTS,这种方式非常随意,没有就没有,有就有,有点无所谓的态度,反正是支持的。
(5)如果没有,就以非事务方式执行;如果有,就将当前事务挂起。这就是PROPAGATION_NOT_SUPPORTS,这种方式非常强硬,没有就没有,有也不支持,挂起来,不管它。
(6)如果没有,就以非事务方式执行;如果有,就抛出异常。这就是PROPAGATION_NEVER,这种方式更强硬,没有就没有,有了反而报错,它对大家宣称:我从不支持事务。
(7)如果没有,就抛出异常;如果有,就使用当前事务。这就是PROPAGATION_MANDATORY,这种方式可以说是最强硬的,没有事务就直接报错,它对世界说:我必须要有事务。
Spring的事务传播行为,确实是一个分厂强大而又使用的功能。除此之外,它还提供了一些小的附加功能,比如:
1、事务超市(Transaction Timeout)——为了解决事务时间太长,消耗太多资源的问题,所以故意给事务设置一个最大时长,如果超时了,就回滚事务。
2、只读事务(Readonly Transaction)——为了忽略哪些不需要事务的方法,比如读取数据,这样可以有效的提供啊一些性能。
在Spring配置文件中使用:
...
<tx:annotation-driven />
...
在需要事务的方法上使用:
@Transactional
public void xxx() {
...
}
可在 Transactional 注解中设置事务的隔离级别、事务传播行为、事务超时时间、是否只读事务。