【问题标题】:Why does nullable = false force a FK to be put in on insert, but without it it does an update to set the FK in JPA/Hibernate为什么 nullable = false 强制在插入时放入 FK,但没有它会更新以在 JPA/Hibernate 中设置 FK
【发布时间】:2013-05-30 15:18:02
【问题描述】:

使用 JPA 注释和 hibernate,我们最近遇到了一个单向单映射问题,如下所示:

@Entity
public class FooOrder extends AbstractEntity{

    @OneToMany(cascade= CascadeType.ALL,orphanRemoval = true)
    @JoinColumn(name = "fooOrderId")
    private List<FooItem> fooItems = new ArrayList<FooItem>();
    public void addFooItem(foo item properties here)
    {
       fooItems.add(fooItem);
    }
}


@Entity
public class FooItem extends AbstractEntity {

   SomeRandomStuffButNoLinkToParent
}

测试代码基本上是这样的:

FooOrder fooOrder = new FooOrder(stuff here);

fooOrder.addFooItem(foo item properties here);

fooOrder = fooOrderRepository.save(fooOrder);

当我们对此运行测试时,我们会得到如下所示的 sql:

insert FooOrder(columns here)
insert FooItem(columns here missing the FK to FooOrder)
update FooItem set FooOrderFK to proper key.

但如果我设置@JoinColumn(name = "activeOrderId", nullable = false) 那么我的 sql 看起来像这样:

insert FooOrder(columns here)
insert FooItem(columns here with FK to FooOrder)

为什么hibernate可以通过update来设置FK,如果FK可以为空,却在不可以为空的时候在insert中设置?

【问题讨论】:

  • 为什么会出现问题?这似乎是休眠中的实现/设计决策
  • 我碰巧遇到了这个问题,因为数据库中的一个字段被设置为不可为空,即使映射没有反映这一点。遇到是件好事,因为它让我们知道我们有一个不匹配,但我认为这很有趣,而且如果一个就足够了,做 2 次操作似乎很奇怪。
  • 如果 fk-column 不可为空,实体上的持久化操作必须自动失败;如果不是,则关系上的插入操作可能会自行失败,恢复(提交主实体或回滚所有内容)将留给您的代码。

标签: java hibernate jpa


【解决方案1】:

当外键不能为空时

insert FooOrder(columns here)
insert FooItem(columns here with FK to FooOrder)

是实际执行插入的唯一方法。所以真正的问题是为什么不总是这样做。

我对此的看法是,使用更新的方式在另一个永远无法工作的时候工作。

假设我们有某种循环外键关系。 A 有 B 的外键 B 有 A 的外键 如果这些外键都不是可以为空的,则可能无法插入它。 您不能先插入 A,因为 B 的外键不能为空。 B也一样。

还请注意,我的示例可能过于简单化。这个循环外键可以由任意数量的表引起。

因此,首先插入数据然后添加外键只是在这个更复杂的场景中的工作方式。您的非空约束迫使 Hibernate 采取另一种方式。对于默认情况,首先插入然后添加键只是他更好的主意。

【讨论】:

    猜你喜欢
    • 2022-01-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-16
    • 2019-01-02
    • 2016-09-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多