这与标题中所说的不完全相同,但是接近。考虑一下这些Spring bean:
@Bean
class BeanA {
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = EvilException.class)
public void methodA() {
/* ... some actions */
if (condition) {
throw new EvilException();
}
}
}
@Bean
class BeanB {
@Autowired private BeanA beanA;
final int MAX_TRIES = 3;
@Transactional(propagation = Propagation.NESTED)
public void methodB() {
// prepare to call Bean A
try {
beanA.methodA();
/* maybe do some more things */
}
catch (EvilException e) {
/* recover from evil */
}
}
}
@Bean
class MainWorkerBean {
@Autowired private BeanB beanB;
@Autowired private OtherBean otherBean;
@Transactional(propagation = Propagation.REQUIRED)
public void doSomeWork() {
beanB.methodB();
otherBean.doSomeWork();
}
}
重要说明:我正在使用支持保存点的JDBC事务管理器。
我期望这样做是,当引发EvilException
时,BeanA
的事务将回滚,通过此设置,该事务恰好是通过启动methodB
创建的保存点。但是,事实并非如此。
当使用调试工具时,我看到的是这样:
doSomeWork
的MainWorkerBean
开始时,创建新交易methodB
启动时,事务管理器正确地初始化了一个保存点,并将其交给TransactionInterceptor
methodA
启动时,事务管理器再次看到Propagation.REQUIRED
,并再次发出对实际JDBC事务的干净引用,但不知道保存点这意味着抛出异常时,TransactionStatus::hasSavepoint
返回false
,这将导致整个全局事务的回滚,因此恢复和进一步的步骤就像丢失一样好,但是我的实际代码不知道回滚(因为我已经为此写了恢复文件)。
[暂时,我不考虑将BeanA
的交易更改为Propagation.NESTED
。诚然,看起来它将允许我进行更多的本地回滚,但是它将变得太本地化,因为据我了解,Spring将会有两个保存点,并且只会回滚BeanA
保存点,而不是BeanB
保存点]一,如我所愿。
还有其他我想念的东西,例如配置选项,会使得Propagation.REQUIRED
的内部事务认为它在保存点内运行,并回滚到保存点,而不是全部回退?
目前,我们正在使用Spring 4.3.24,但是我已经爬过了他们的代码,无法发现任何相关的更改,因此我认为升级不会对我有帮助。
如此故障单所描述:https://github.com/spring-projects/spring-framework/issues/11234
对于弹簧版本<5.0,在所述情况下,全局事务设置为'仅回滚'。
在此事务中,我正在处理几个任务。如果在单个任务期间发生错误,我不希望整个事务回滚,因此我将任务处理包装在另一个事务边界中,并传播PROPAGATION_NESTED。
问题出现在任务处理期间,调用以PROPAGATION_REQUIRED事务边界定义的现有服务方法。这些方法抛出的任何运行时异常都会导致将基础连接标记为仅回滚,而不是考虑当前的父事务嵌套传播。
[...]
从Spring Framework 5.0开始,嵌套事务将在回滚到保存点时解析其仅回滚状态,不再将其应用于全局事务。
在旧版本上,建议的解决方法是在这种情况下将
globalRollbackOnParticipationFailure
切换为false
。
但是,即使对于Spring5,我在重现问题时也注意到,嵌套事务可能会回滚,包括在methodB()的catch块中所做的所有事情。因此,您的恢复代码可能无法在methodB()内运行,具体取决于您的恢复情况。如果methodA()不是事务性的,那将不会发生。只是要提防的事情。
此处有更多详细信息:https://github.com/spring-projects/spring-framework/issues/8135