JPA OneToMany不删除子级


158

我对@OneToMany父实体和子实体之间的简单映射有疑问。一切正常,只有当我从集合中删除子记录时,才会删除它们。

父母:

@Entity
public class Parent {
    @Id
    @Column(name = "ID")
    private Long id;

    @OneToMany(cascade = {CascadeType.ALL}, mappedBy = "parent")
    private Set<Child> childs = new HashSet<Child>();

 ...
}

孩子:

@Entity
public class Child {
    @Id
    @Column(name = "ID")
    private Long id;

    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(name="PARENTID", nullable = false)
    private Parent parent;

  ...
}

如果我现在从childs集合中删除and child,它不会从数据库中删除。我尝试取消child.parent引用,但这也不起作用。

实体在Web应用程序中使用,删除是Ajax请求的一部分。按下保存按钮时,我没有已删除子项的列表,因此无法隐式删除它们。

Answers:


253

JPA的行为是正确的(按照规范的含义):不能仅仅因为已从OneToMany集合中删除了对象就删除了对象。有特定于供应商的扩展可以执行此操作,但本机JPA不能满足此要求。

在某种程度上,这是因为JPA实际上不知道是否应删除从集合中删除的内容。用对象建模的术语来说,这就是组合和“聚合*” 之间的区别。

组合中,子实体没有父实体就不存在。一个典型的例子是在房屋和房间之间。删除房子,房间也去。

聚合是一种较宽松的关联,以课程和学生为代表。删除课程,并且学生仍然存在(可能在其他课程中)。

因此,您需要使用特定于供应商的扩展来强制执行此行为(如果可用),或者显式删除子级并将其从父级集合中删除。

我知道:


感谢很好的解释。就像我担心的那样 (我询问之前曾做过一些搜索/阅读,只是想保存一下)。不知何故,我开始后悔直接使用JPA API和nit Hibernate的决定..我将尝试使用Chandra Patni指针并使用hibernate delete_orphan级联类型。
伯特2010年

我对此也有类似的疑问。请在这里看看这个帖子好吗?stackoverflow.com/questions/4569857/...
升范

77
使用JPA 2.0,您现在可以使用选项orphanRemoval = true
itsadok'2

2
关于orphanRemoval的出色的初步解释和好的建议。不知道JPA没有考虑这种删除。我对Hibernate的了解与JPA实际上所做的之间的细微差别可能令人发疯。
2012年

很好地解释了组成和聚合之间的区别!
FelipeLeão17年



20

如前所述,无法用JPA来完成我想做的事情,因此我使用了hibernate.cascade批注,由此,Parent类中的相关代码现在看起来像这样:

@OneToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH}, mappedBy = "parent")
@Cascade({org.hibernate.annotations.CascadeType.SAVE_UPDATE,
            org.hibernate.annotations.CascadeType.DELETE,
            org.hibernate.annotations.CascadeType.MERGE,
            org.hibernate.annotations.CascadeType.PERSIST,
            org.hibernate.annotations.CascadeType.DELETE_ORPHAN})
private Set<Child> childs = new HashSet<Child>();

我不能简单地使用“ ALL”,因为这也会删除父对象。




3
@Entity 
class Employee {
     @OneToOne(orphanRemoval=true)
     private Address address;
}

这里

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.