使用JPA注释和hibernate,我们最近遇到了一个单向的onetomany映射,看起来像这样:
@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);
当我们对此运行测试时,我们得到的结果如下:
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,如果它可以为空,但是当它不可为空时在插入中设置它?
答案 0 :(得分:0)
当外键不能为空时
insert FooOrder(columns here)
insert FooItem(columns here with FK to FooOrder)
是实际执行插入的唯一方法。所以真正的问题是为什么并不总是这样做。
我对此的看法是,使用更新的方式适用于另一方无法工作的时候。
假设我们有一些循环的foreingn关键关系。 A有B的外键 B有A的外键 如果这些外键都不可为空,则可能无法插入此键。 您不能先插入A,因为B的外键不能为空。 B也是如此。
另请注意,我的示例可能会过度简化。这个循环外键可以由任意数量的表引起。
因此,首先插入数据然后添加外键只是在这个更复杂的场景中工作的方式。你的非空约束迫使Hibernate采取另一种方式。对于默认情况,首先插入然后添加键只是他更好的想法。