【问题标题】:Hibernate update before insert in one to many一对多插入前休眠更新
【发布时间】:2021-07-28 20:52:00
【问题描述】:

由于 Hibernate 执行的操作顺序,我收到了约束冲突异常。我定义了以下实体。

@Entity
public class A {

    @Id
    private Integer id;

    @OneToMany(mappedBy = "a", fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
    private List<B> bList;

    public void setBList(List<B> bList) {

        if(CollectionUtils.isNotEmpty(this.bList)) {
            this.bList.clear();
        }

        if(CollectionUtils.isNotEmpty(bList)) {
            this.bList.addAll(bList);
        }
    }
}

@Entity
@Table(uniqueConstraints={@UniqueConstraint(columnNames = {"name", "a_id", "isDeleted"})})
public class B {

    @Id
    private Integer id;

    private String name;

    @ManyToOne(fetch = FetchType.LAZY, optional = false)
    @JoinColumn(name="a_id")
    private A a;

    private boolean isDeleted;
}

当我在实体 A 中设置新的 B 列表(包含一个更新为已删除的项目和一个在与约束对应的列中具有相同值的新项目)并保存实体 A 时,我得到约束违规。

Hibernate 在将旧项目更新为已删除之前执行新项目的插入,这会导致违反约束,而实际上应用程序中的数据是正确的。

我在这里做错了什么还是有任何配置或修复?

【问题讨论】:

    标签: java sql-server hibernate


    【解决方案1】:

    由于 OP 的评论指出它没有抓住重点,答案在 2021/05/07 发生了变化

    你应该改变两件事以使事情正常工作

    1. 您不应该依赖 Hibernate 来为您猜测正确的操作顺序。它依赖于可能不符合您意图的启发式方法。在您的情况下,您应该在软删除旧的B 之后并在保留新的之前调用EntityManager.flush

    2. 无论如何,当您软删除您的第二个 B 时,您的唯一约束会导致问题,这与唯一列相同。 以后有更多

    一般来说,确保 DB 中的这种约束是一个坏主意。如果您尝试更新/插入违反它们的实体,那么您将得到一个不起眼的PersistenceException,并且很难警告您的用户确切原因。因此,无论如何,您必须在插入/更新之前以编程方式检查这些约束。因此,您最好删除它们并通过您的程序确保唯一性,除非它们对数据完整性至关重要。不可为空的列和其他纯业务逻辑约束也是如此。

    现在根据经验得出最后一条建议:对于软删除列,请使用 TimeStamp 而不是 boolean。更新和阅读记录的工作量相同,但它会为您提供一些有关何时删除记录的有价值信息。

    【讨论】:

    • setBList setter 的bList 参数中的每个条目都已经有A set 的引用。我不认为这是我在这里面临的问题。
    • 对不起,我读了你的帖子有点太快了,没有抓住重点。我还有话要说。所以我要完全改变我的答案
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-29
    • 1970-01-01
    相关资源
    最近更新 更多