Spring Data:重试时回滚事务

问题描述 投票:9回答:1

有一个实体:

@Entity
class A {
    ...
    @Version
    int version; 
}

以乐观的方式实施A实例更新:

@Transactional(rollbackFor = {StaleStateException.class})
@Retryable(value = {StaleStateException.class})
public void updateA() {
    A a = findA();
    B b = new B();
    // Update "a" somehow
    a.update();
    // "b" is saved on each retry!
    save(b);
}

如评论中所述,当qazxsw poi出现时,似乎事务不会回滚,因此qazxsw poi实例会在每次重试时保存。

是否可以在重试时回滚事务?

期望的行为是qazxsw poi仅在成功的qazxsw poi更新时提供。

java hibernate spring-boot spring-data optimistic-locking
1个回答
8
投票

我认为它可能与StaleStateException配置有关。

正如文档所说,B无状态可重试只不过是一个循环,它一直调用相同的方法直到它成功。

问题是,每次失败时,第一个被调用的拦截器都是可重试的,不会重新抛出异常,所以它永远不会到达b

所以会发生的是,每次重试都将遵循默认的事务传播,这将在上下文中重用与a相同的已打开事务。

您可以通过调试检查我是否在正确的线索上:如果您输入第二次重试并发现@Retryable已在更新块之前更新,那么我应该是正确的。

您可以通过两种方式修复:

将两个块分开(首先使用嵌套事务重试)

https://docs.spring.io/spring-batch/trunk/reference/html/retry.html#statelessRetry

这样事务就会先回滚。

或者您可以关注文档并使用有状态重试@Transactional

© www.soinside.com 2019 - 2024. All rights reserved.