PROPAGATION_REQUIRED事务属性



在http://www.vermatech.com/code/SpringTransactionExamples.html给出的第一个案例研究中,程序正在调用两个方法,即

testModel.deleteAllCountries();
testModel.initializeCountries();

where initializeCountries抛出运行时异常。这两个方法的事务定义属性都是PROPAGATION_REQUIRED。仍然在deleteAllCountries下进行交易方法被提交,但initializeCountries下的事务被回滚(根据同一案例研究中给出的日志)。

根据PROPAGATION_REQUIRED定义,它支持当前事务;如果不存在,请创建一个新的。我的问题是initializeCountries方法下的事务应该支持deleteAllCountries方法下的事务。我的意思是,这两种方法都应该被视为单一事务。根据我的理解,应该提交完整的事务还是回滚?不知道为什么日志将它们分开处理

"需要传播"定义为

支持当前事务,如果不存在,创建一个新的。

在上面的例子中,deleteAllCountries方法在事务中执行并提交。调用initializeCountries时没有当前事务,因此它在第二个事务中执行,并且回滚它对第一个方法所做的更改没有影响。

传播适用于嵌套方法调用,而不适用于连续的方法调用。如果你看一下文档:

当传播设置为PROPAGATION_REQUIRED时,逻辑为设置所依赖的每个方法创建事务范围应用。每个这样的逻辑事务范围都可以确定单独的仅回滚状态,具有外部事务作用域在逻辑上独立于内部事务范围。的当然,在标准PROPAGATION_REQUIRED行为的情况下,所有这些作用域将映射到相同的物理事务。所以一个在内部事务作用域中设置的仅回滚标记会产生影响外部事务实际提交的机会(如您所期望的)

)。

但是,在内部事务作用域设置仅回滚标记时,外部事务尚未决定回滚本身,因此回滚(由内部静默触发)事务范围)是意外的。一个相应的此时会抛出unexpected drollbackexception。这是意料之中的行为,使事务的调用者永远不会被误导到假设执行了一个提交,而实际上没有执行。所以如果内部事务(外部调用者不知道)是静默的将事务标记为仅回滚,外部调用者仍然调用提交。外部调用者需要接收一个untedrollbackexception,以清楚地指示回滚执行。

那么你可以看到所有这些都是关于内部和外部的,没有一个提到连续的调用。在您的示例中,对deleteAllCountries的调用是最外层的事务方法,因此当它成功完成时,Spring将立即提交事务。然后,对initializeCountries的调用必须在单独的事务中执行,它是最外层的方法。

您的假设似乎是Spring将在第一个方法完成后保持事务打开,但这不是它的工作方式。为了获得想要的效果,可以在testModel上创建另一个方法,该方法包装了对deleteAllCountries和initializeCountries的调用,使该方法具有事务性,并为其赋予PROPAGATION_REQUIRED属性。这样,第二个方法的回滚将导致第一个方法的更改也回滚,因为包装方法将它们分组在一起。否则没有任何东西告诉Spring,这些东西应该是同一个事务的一部分。

最新更新