不久前,为了避免事务的嵌套,刻意去修改以前的设计,导致各部分之间经常出现职责的混淆和重复,颇为头痛.今天在一篇名为《解惑 spring 嵌套事务》文章中找到了答案.
原因出在没有能够深刻理解事务声明中不同事务传播属性配置的的含义.原来想象是这样的(见下面示例代码),serviceA和ServiceB的所有方法都被配置声明事务,当serviceA的方法调用ServiceB的方法,我便"顺理成章"的认为methodA和methodB都各自有自己的事务,这会带来两个问题:1)性能下降;2)methodB事务提交后,methodA因异常而回滚,methodB去无法回滚.
ServiceA { /** * 事务属性配置为 PROPAGATION_REQUIRED */ void methodA() { ServiceB.methodB(); } } ServiceB { /** * 事务属性配置为 PROPAGATION_REQUIRES_NEW */ void methodB() { } }
如果理解了事务传播属性的含义就不会出现这样的误解.见下方解释:
PROPAGATION_REQUIRED -- 支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。 |
其实若事务传播属性配置为PROPAGATION_REQUIRED,上例中的问题根本不会出现.因为根据上方的解释,当methodB执行的时候,当前线程已经开始了一个事务,所以methodB是不会产生新的事务,也就意味着随之而来的两个问题是不存在的.除非对methodB使用了PROPAGATION_REQUIRES_NEW的配置,才会使得methodB有自己的事务.
关于PROPAGATION_NESTED所指的嵌套,还请参见《解惑 spring 嵌套事务》.