使用JPA删除集合中的子元素

24

我在我的 Web 应用程序中使用 JPA 覆盖 Hibernate。下面是两个实体(仅显示 getter):

class Child {
  private Parent parent;

  @ManyToOne(optional=false)
  @JoinColumn(name="parent_id", referencedColumnName="parent_id", nullable=false, updatable=false)
  public Parent getParent() {
    return parent;
  }
}

class Parent {
  private Collection<Child> children;

  @OneToMany(fetch=FetchType.EAGER, mappedBy="parent", cascade={CascadeType.ALL})
  public Collection<Child> getChildren() {
    return children;
  }
}

如您所见,ParentChild之间的关系是“一对多”的。

现在我需要加载一个Parent实例,删除一些或所有子元素,并保存更改。以下代码对我无效:

Parent p = entityManager.find(Parent.class, 12345L); // load entity
p.getChildren().clear(); // remove all children
entityManager.merge(p); // try to save

以上示例中未删除子实体。现在我必须手动调用entityManager.remove()来删除每个子实体。

是否有更简单的方法来管理子集合?

请注意,我不想使用特定于Hibernate的功能,只想使用纯JPA。


可能是JPA CascadeType.ALL不会删除孤儿的问题的重复。 - Pascal Thivent
1个回答

34

对于 JPA 2.0,您可以在 @OneToMany 上设置 orphanRemoval=true

对于 JPA 1.0,您应该使用特定于 Hibernate 的注释。即使用值为 @Cascade (而不是属性 cascade)的注释。

@Cascade({CascadeType.ALL, CascadeType.DELETE_ORPHAN})

Hibernate 3.5+ 实现了 JPA 2.0


有没有针对 JPA 1.0 的解决方案?我还不准备更改 JPA 实现者。 - Andrey
谢谢,这是一个好方法。设置orphanRmoval,当合并时可以删除孤立的子项。 - Scarlett
关于orphanRemoval,EntityManager如何准确区分从集合中明确删除的对象(因此需要在数据库中删除)和从未加载到集合中的对象(即因为一对多集合是延迟加载)?或者它只适用于EAGER集合? - Marcus Junius Brutus
它将集合的状态与数据库的状态进行比较。因此,如果集合中缺少某些内容(无论原因如何),但是在数据库中存在,则会从数据库中删除。 - Bozho
谢谢。即使使用JPA2.0,@Cascade对我来说仍然是唯一的解决方案。奇怪。 - Bodosko

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接