使用hibernate一对一引用完整性

我有两张桌子 –

Foo {foo_id,name}
Foo_properties {fp_id,foo_id,phoneNumber}

现在我想使用hibernate在我的对象模型中映射它。我需要在Foo_properties中使用foo_id,因为我想保持参照完整性并希望添加ON DELETE CASCADE约束。
所以我用以下方式映射关系 –

@Entity public class Foo{ @Id private long foo_id; private String name; @OneToOne(mappedBy = "foo") private FooProperties fooProperties; } @Entity public class FooProperties{ @Id private long fp_id; private String phoneNumber; @OneToOne @JoinColumn(name = "foo_id", nullable = false) private Foo foo; } 

既然拥有方是FooProperties类,我面临以下问题 –

如果我将FooProperties的新实例设置为Foo,则现有的FooProperties仍然保留在DB中,而hibernate不会删除该实例,例如

 Foo foo = entityManager.find(Foo.class, fooId); foo.setFooProperties(new FooProperties("xxx-xxx-xxx")); entityManager.merge(foo); 

这导致FooProperties表中的新行以及现有行。 现在我不明白我如何改变我的映射,所以我可以让上面的代码(或它的变体)适用于所有场景,这意味着我需要Foo作为拥有方和FooProperties中的foo_id。 有没有办法像这样定义映射?

注意:我已经根据这个问题提出了问题 ,但我认为我在上一个问题中并不清楚,所以又问了另一个问题。

您已被告知使用orphanRemoval = trueCascadeType.DELETE_ORPHAN 。 但是,由于对JPA规范的解释具有欺骗性,因此对于一对一的关系( HHH-5559 )不会如预期的那样起作用。

您可以使用以下技巧实现orphanRemoval的正确行为:

 @Entity public class Foo{ @OneToMany(mappedBy = "foo", orphanRemoval = true) private List fooProperties; public FooProperties getFooProperties() { if (fooProperties == null || fooProperties.isEmpty()) return null; else return fooProperties.get(0); } public void setFooProperties(FooProperties newFooProperties) { if (fooProperties == null) fooProperties = new ArrayList(); else fooProperties.clear(); if (newFooProperties != null) fooProperties.add(newFooProperties); } ... } @Entity public class FooProperties{ @ManyToOne @JoinColumn(name = "foo_id", nullable = false) private Foo foo; ... } 

或者甚至是这个,如果你不需要FooPropeties.foo

 @Entity public class Foo{ @OneToMany(orphanRemoval = true) @JoinColumn(name = "foo_id", nullable = false) private List fooProperties; // getter/setter as above ... } 

我认为不是在实体上调用merge,如果直接调用session对象上的update,那么hibernate将首先删除现有的行,然后它将添加新的行。 我实现了相同的,但在我的情况下,我使用xml映射实体。 我希望这能帮到您。

Bar是关联的所有者(由反面的mappedBy表示),因此必须在那里设置级联。

编辑:

要反过来, 这可能会有所帮助。

有两个选项供您选择,因为您不想更改映射:

  1. 通过您的服务层逻辑来完成。 我想你已经有了类似的问题。
  2. 在关系的Foo端使用Hibernate注释@Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN)。 然而,这是明确的Hibenate和JPA 2不包括对相同的支持。