首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >意外复制键异常

意外复制键异常
EN

Stack Overflow用户
提问于 2019-02-12 18:58:30
回答 2查看 634关注 0票数 0

我看到了SpringBoot2.0.4+ Hibernate的奇怪行为。

我有一个包含随机生成代码的实体。如果已经为另一个实体设置了生成的代码,则会按预期抛出一个DataIntegrityViolationException。这样,循环就可以用新代码再试一次,希望它不会被使用。当这种情况发生时,循环将继续,生成一个新代码,对saveAndFlush()的调用再次抛出相同的异常,说明已经使用了导致问题的原始代码(前一次迭代)(重复)。不过,我现在正在设置一个新代码,而不是异常提到的代码。

我唯一能想到的是Hibernate不会从“队列”中删除操作,所以当第二次调用saveAndFlush()时,它仍然尝试执行第一次保存,然后执行新的保存。显然,第一次保存失败了,就像第一次迭代期间一样。也许我错了,但这是怎么回事?

代码语言:javascript
复制
@Entity
public class Entity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(nullable = false, unique = true)
    private int code;

    public void setCode(int code) {
        this.code = code;
    }

    //Other properties

}

@Transactional
public void myFunction() {
    boolean saved = false;
    do {
        int code = /* Randomly generated code */;
        if(entity == null) {
            entity = new Entity(code, /* other properties */);
        } else {
            entity.setCode(code);
        }

        try {
            entity = myRepository.saveAndFlush(entity);
            saved = true;
        } catch (DataIntegrityViolationException e) {
            /* Ignore so that we can try again */
        }
    } while(!saved);
}

编辑:

如果我用saveAndFlush()替换save(),问题就会消失。我在某个地方看到,如果flush()也被调用,那么在上次保存失败后进行保存可能会有问题。这正是我的案子。然而,我不明白为什么这是一个问题。我调用saveAndFlush()而不是save()的唯一原因是捕获重复的键异常。使用save(),如果Hibernate不直接执行INSERTUPDATE,则在提交事务之前发生的刷新过程中抛出异常,这不是我想要的。

EN

回答 2

Stack Overflow用户

发布于 2020-10-07 11:14:25

在这种情况下,您需要重新启动事务,因为错误已经绑定到事务上下文/会话。

因此,将重试逻辑置于事务边界之外,或者如果需要维护完整性(全部保存或未保存),首先检查是否存在重试逻辑,以避免抛出异常。

票数 0
EN

Stack Overflow用户

发布于 2019-02-12 20:15:43

如果调试代码并查看持久性上下文的状态,您可能会得到答案。您是正确的,hibernate维护一个排序队列,即在事务期间执行的所有查询都将在提交/刷新上运行。

请张贴您在调试时获得的持久性上下文的值。

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54656941

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档