4

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

@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在可以为空的情况下通过更新设置FK,但在不可为空的情况下将其设置在插入中?

4

1 回答 1

0

那么当外键不能为空时

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

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

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

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

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

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

于 2013-08-07T19:56:59.840 回答