java – 春天的PROPAGATION_REQUIRED事务属性?
作者:互联网
在http://www.vermatech.com/code/SpringTransactionExamples.html给出的第一个案例研究中,
程序正在调用两种方法,即
testModel.deleteAllCountries();
testModel.initializeCountries();
其中initializeCountries抛出运行时异常.对于这两种方法,事务定义属性为PROPAGATION_REQUIRED.仍在deleteAllCountries下进行交易
方法得到提交但是initializeCountries下的事务被回滚(根据同一案例研究中给出的日志).
根据PROPAGATION_REQUIRED定义,它支持当前事务;如果不存在则创建一个新的.所以我的问题是initializeCountries方法下的事务
应该支持deleteAllCountries方法下的事务.我的意思是这两种方法都应该被视为单一交易.根据我的理解,还是应该提交或回滚完整的事务?不知道日志是如何分别处理它们的.
解决方法:
“需要传播”定义为
Support a current transaction, create a new one if none exists.
在上面的例子中,deleteAllCountries方法在事务中执行并提交.调用initializeCountries时没有当前事务,因此它在第二个事务中执行,并且回滚它对第一个方法所做的更改没有影响.
传播适用于嵌套方法调用,而不适用于连续调用.如果你看一下the documentation:
When the propagation setting is PROPAGATION_REQUIRED, a logical
transaction scope is created for each method upon which the setting is
applied. Each such logical transaction scope can determine
rollback-only status individually, with an outer transaction scope
being logically independent from the inner transaction scope. Of
course, in case of standard PROPAGATION_REQUIRED behavior, all these
scopes will be mapped to the same physical transaction. So a
rollback-only marker set in the inner transaction scope does affect
the outer transaction’s chance to actually commit (as you would expect
it to).However, in the case where an inner transaction scope sets the
rollback-only marker, the outer transaction has not decided on the
rollback itself, and so the rollback (silently triggered by the inner
transaction scope) is unexpected. A corresponding
UnexpectedRollbackException is thrown at that point. This is expected
behavior so that the caller of a transaction can never be misled to
assume that a commit was performed when it really was not. So if an
inner transaction (of which the outer caller is not aware) silently
marks a transaction as rollback-only, the outer caller still calls
commit. The outer caller needs to receive an
UnexpectedRollbackException to indicate clearly that a rollback was
performed instead.
那么你可以看到所有这些都是关于内在和外在的 – 没有一个提到连续的呼叫.在您的情况下,对deleteAllCountries的调用是最外层的事务方法,因此当它成功完成时,Spring立即提交事务.然后你对initializeCountries的调用必须在一个单独的事务中执行,它是最外层的方法.
您的假设似乎是Spring将在第一个方法完成后保持事务处于打开状态,但这不是它的工作原理.为了获得您想要的效果,您可以在testModel上创建另一个方法,该方法包含对deleteAllCountries和initializeCountries的调用,使该方法具有事务性并为其提供属性PROPAGATION_REQUIRED.这样,第二种方法的回滚将导致第一种方法的更改也被回滚,因为包装方法将它们组合在一起.否则什么都没有告诉Spring这些东西应该是同一个交易的一部分.
标签:java,spring,java-ee,spring-transactions 来源: https://codeday.me/bug/20190715/1470993.html