Spring @Transactional 注解属性优先/继承
Spring @Transactional Annotation properties precedence / inheritance
在 REQUIRED
传播的情况下,当调用方方法本身是事务性的时,如果它们不同,当前方法是否会覆盖封闭的事务属性(例如 rollbackFor)?
插图:
Class A {
@Transactional(propagation = Propagation.REQUIRED,
rollbackFor = { SomeException.class})
void foo() {
try {
b.bar();
} catch (OtherException e) {
// is the transaction marked as rollback-only at this point ?
}
}
}
Class B {
@Transactional(propagation = Propagation.REQUIRED,
rollbackFor = { OtherException.class})
void bar() {
[...]
}
}
编辑 :
好吧,我想避免琐碎的超出范围的答案,所以让我们明确一点,我知道 spring 传播处理。
如果你不是,下面是文档的相关部分,我只想澄清关于我上面的例子的第一部分:
PROPAGATION_REQUIRED
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.
我的问题可以改写为:
逻辑事务范围是否包含事务属性?
请参阅 spring documentation 的第 16.5.7 节。
即使在事务上下文中调用内部方法时使用 REQUIRED 进行注释,它也会映射到相同的物理事务。
根据我对规格的理解,我会在这个例子中说:
Class A {
@Transactional(propagation = Propagation.REQUIRED,
rollbackFor = { SomeException.class})
void foo() {
try {
b.bar();
} catch (OtherException e) {
// the transaction is marked as rollback-only by the inner call as it thrown an OtherException
// XXX --- or not if inner logical scope does not handle overridden property 'rollbackFor' ? ---
// anyway, we avoid UnexpectedRollbackException by enforcing physical rollback to outter scope programmatically, by throwing :
throw new SomeExeption(e);
}
}
}
Class B {
@Transactional(propagation = Propagation.REQUIRED,
rollbackFor = { OtherException.class})
void bar() {
[...]
}
}
因此我们可以将问题重新表述为:覆盖的 "rollbackFor" 属性 是否由内部逻辑事务范围管理处理?
顺便问一下,您使用的具体事务管理器 class 和版本是什么?
所以,我设置了一个测试用例,简短的回答是。
事务逻辑范围包含事务属性,其边界确实是注释方法的边界。
因此,即使两种方法的底层物理事务相同,逻辑属性对于每个方法都是适当的,并且内部方法可以强制回滚外部方法事务。
但是,如果这最后一次触发提交,它将导致 UnexpectedRollbackException。
比照。 Spring TransactionInterceptor(评论是我的)
try {
retVal = invocation.proceed();
}
catch (Throwable ex) {
completeTransactionAfterThrowing(txInfo, ex);
throw ex;
}
完成交易后抛出():
// txinfo is proper to the invocation target method
if (txInfo.transactionAttribute.rollbackOn(ex)) {
try {
txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus());
}
AbstractPlatformTransactionManager.processRollback() :
else if (status.isNewTransaction()) { //requiresnew
doRollback(status);
}
else if (status.hasTransaction()) { //requiered
[...]
doSetRollbackOnly(status);
}
}
在 REQUIRED
传播的情况下,当调用方方法本身是事务性的时,如果它们不同,当前方法是否会覆盖封闭的事务属性(例如 rollbackFor)?
插图:
Class A {
@Transactional(propagation = Propagation.REQUIRED,
rollbackFor = { SomeException.class})
void foo() {
try {
b.bar();
} catch (OtherException e) {
// is the transaction marked as rollback-only at this point ?
}
}
}
Class B {
@Transactional(propagation = Propagation.REQUIRED,
rollbackFor = { OtherException.class})
void bar() {
[...]
}
}
编辑 :
好吧,我想避免琐碎的超出范围的答案,所以让我们明确一点,我知道 spring 传播处理。
如果你不是,下面是文档的相关部分,我只想澄清关于我上面的例子的第一部分:
PROPAGATION_REQUIRED
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.
我的问题可以改写为:
逻辑事务范围是否包含事务属性?
请参阅 spring documentation 的第 16.5.7 节。 即使在事务上下文中调用内部方法时使用 REQUIRED 进行注释,它也会映射到相同的物理事务。
根据我对规格的理解,我会在这个例子中说:
Class A {
@Transactional(propagation = Propagation.REQUIRED,
rollbackFor = { SomeException.class})
void foo() {
try {
b.bar();
} catch (OtherException e) {
// the transaction is marked as rollback-only by the inner call as it thrown an OtherException
// XXX --- or not if inner logical scope does not handle overridden property 'rollbackFor' ? ---
// anyway, we avoid UnexpectedRollbackException by enforcing physical rollback to outter scope programmatically, by throwing :
throw new SomeExeption(e);
}
}
}
Class B {
@Transactional(propagation = Propagation.REQUIRED,
rollbackFor = { OtherException.class})
void bar() {
[...]
}
}
因此我们可以将问题重新表述为:覆盖的 "rollbackFor" 属性 是否由内部逻辑事务范围管理处理?
顺便问一下,您使用的具体事务管理器 class 和版本是什么?
所以,我设置了一个测试用例,简短的回答是。
事务逻辑范围包含事务属性,其边界确实是注释方法的边界。
因此,即使两种方法的底层物理事务相同,逻辑属性对于每个方法都是适当的,并且内部方法可以强制回滚外部方法事务。 但是,如果这最后一次触发提交,它将导致 UnexpectedRollbackException。
比照。 Spring TransactionInterceptor(评论是我的)
try {
retVal = invocation.proceed();
}
catch (Throwable ex) {
completeTransactionAfterThrowing(txInfo, ex);
throw ex;
}
完成交易后抛出():
// txinfo is proper to the invocation target method
if (txInfo.transactionAttribute.rollbackOn(ex)) {
try {
txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus());
}
AbstractPlatformTransactionManager.processRollback() :
else if (status.isNewTransaction()) { //requiresnew
doRollback(status);
}
else if (status.hasTransaction()) { //requiered
[...]
doSetRollbackOnly(status);
}
}