许多人不删除子女

我在父实体和子实体之间的简单 @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;


...
}

如果我现在从子集中删除和子集,它不会从数据库中删除。我试图取消 child.parent引用,但是这也不起作用。

这些实体在 Web 应用程序中使用,删除作为 Ajax 请求的一部分发生。当按下保存按钮时,我没有已删除子元素的列表,所以我不能隐式地删除它们。

179877 次浏览

JPA 的行为是正确的(意味着 按照说明书) : 对象不会仅仅因为您从 OneTomany 集合中删除了它们而被删除。有一些特定于供应商的扩展可以做到这一点,但是本地 JPA 不能满足这一点。

部分原因是因为 JPA 实际上不知道是否应该删除从集合中删除的内容。在对象建模术语中,这是 作文和“聚合 *”之间的区别。

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

聚合 是一种较松散的关联,其典型特征是“课程”和“学生”。删除“课程”,“学生”仍然存在(可能在其他课程中)。

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

我知道:

在这里,移除上下文中的级联意味着如果移除父级,子级将被移除。不是协会。如果使用 Hibernate 作为 JPA 提供程序,则可以使用 冬眠特定的级联进行此操作。

如前所述,不可能对 JPA 执行我想要的操作,因此我使用了 hibernate.cade 注释,使用这个注释,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>();

我不能简单地使用’所有’,因为这将删除父母以及。

除了 cletus 的回答之外,自2010年12月以来的最终版 JPA 2.0@OneToMany注释中引入了一个 orphanRemoval属性。 有关详细信息,请参阅此 博客日志

注意,由于规范相对较新,并非所有 JPA1提供程序都有最终的 JPA2实现。例如,Hibernate 3.5.0-Beta-2版本还不支持这个属性。

你可以试试这个:

@OneToOne(orphanRemoval=true) or @OneToMany(orphanRemoval=true).

你可以试试这个:

@OneToOne(cascade = CascadeType.REFRESH)

或者

@OneToMany(cascade = CascadeType.REFRESH)
@Entity
class Employee {
@OneToOne(orphanRemoval=true)
private Address address;
}

参见 给你

我不知道为什么,但我有同样的问题,我的实体如下:

public class Parent {
@OneToMany(mappedBy = "parent",
cascade = CascadeType.ALL)
private List<Child> childList= new ArrayList<>();
}


public class Child {
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "PARENT_ID", nullable = false)
private Parent parent;
}

当我编写自己的 delete()方法时,我终于可以删除一个子代:

@Modifying
@Query("delete from Child c where c.id = :id")
void deleteById(Long id);

请考虑使用@修改是必要的

我从服务层调用它:

childRepository.deleteById(childInstance.getId());