问题
我在父实体和子实体之间使用simple@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;
...
}
如果我现在从子集Set中删除和子节点,它不会从数据库中删除。我试图取消child.parent
参考,但这也无效。
实体用于Web应用程序,删除是作为Ajax请求的一部分发生的。按下保存按钮时,我没有已删除子项的列表,因此我无法隐式删除它们。
#1 热门回答(225 赞)
JPA的行为是正确的(根据规范的含义):对象不会因为你从OneToMany集合中删除它们而被删除。有特定于供应商的扩展可以做到这一点,但原生JPA不适合它。
在某种程度上,这是因为JPA实际上并不知道是否应删除从集合中删除的内容。在对象建模术语中,这是组合和"聚合*"之间的区别。
在组合中,没有父项,子实体就不存在。一个典型的例子是House和Room之间。删除房子和房间也去。
聚合是一种更松散的关联,以课程和学生为代表。删除课程,学生仍然存在(可能在其他课程中)。
因此,你需要使用特定于供应商的扩展来强制执行此行为(如果可用)或显式删除子项并将其从父集合中删除。
我知道:
- Hibernate:cascade delete_orphan。见10.11。传递性持久性;和
- EclipseLink:称之为"私有制"。请参见如何使用@PrivateOwned注释。
#2 热门回答(65 赞)
除了cletus的回答,JPA 2.0,自2010年12月以来的最终版本,在@OneToMany
注释中引入了orphanRemoval
属性。有关详细信息,请参阅thisblog entry。
请注意,由于规范相对较新,并非所有JPA 1提供程序都具有最终的JPA 2实现。例如,Hibernate 3.5.0-Beta-2 release尚不支持此属性。
#3 热门回答(34 赞)
你可以试试这个:
@OneToOne(orphanRemoval=true) or @OneToMany(orphanRemoval=true)
。