Hibernate:使用一个查询删除所有 children
Hibernate: Delete all children with one query
TL;DR: 是否可以将 Hibernate 配置为使用单个删除查询删除所有 child objects?
完整问题: 我在 Hibernate 5.1 中定义了以下 parent/child 关联:
public class Parent {
@OneToMany(fetch = FetchType.EAGER, mappedBy = "parent", cascade = CascadeType.REMOVE)
private List<Child> children;
}
public class Child {
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "parent_id", nullable = false)
private Parent parent;
}
当我删除 parent object 时,所有 child object 都被删除,如预期的那样,但每个都被单独删除。在我的应用程序中,一个 parent 可能有数千个 children,因此出于性能原因,我需要使用单个查询一次将它们全部删除。
可能的解决方法
- 在删除 parent 之前手动执行我自己的 HQL 查询
DELETE FROM child WHERE parent_id = ?
。这里的缺点是我(和任何其他开发人员)必须记住调用该方法。另外,它基本上绕过了级联删除。
- 允许级联删除发生在数据库级别。由于数据在幕后发生变化,我假设我需要记住手动
.clear()
child 集合以防止 Hibernate 和数据库之间的差异。
编辑: 我看到旧版本的 Hibernate 曾经有 one-shot delete 的概念,但我在最新版本的文档中找不到任何类似的内容。该功能是否已删除?
- 假设您删除了父项。
- 如果其他 table,比如 GrandChild,有外键约束
对于 Child,每个 Child 都有多个 GrandChild 记录,他们
也需要删除。
- 生成多个删除查询的原因是,Hibernate 可以
不知道有没有其他的外键约束
tables,到"Child" table。也可能有一些回调方法需要执行,例如@PreRemove。这就是为什么每个子引用都从数据库中加载并单独删除的原因。
- 简而言之,如果您依赖 Hibernate 来管理您的实体,这
是默认行为。
要么在数据库中明确设置ON DELETE CASCADE,要么标记
带有注释的所需子实体
@org.hibernate.annotations.OnDelete,它会自动添加
"on delete" 在模式生成期间添加到模式。对于您的示例,它将是,
`@OneToMany(fetch = FetchType.EAGER, mappedBy = "parent",
cascade = CascadeType.REMOVE)
@org.hibernate.annotations.OnDelete(
action = @org.hibernate.annotations.OnDeleteAction.CASCADE)
private List<Child> children;
这似乎过于简单,所以我可能没有正确理解您的问题,但是:
Parent parent = parentRepository.findByName("dad");
parent.getChildren().clear();
entityManager.save(parent);
要是我们能.clear() 我们的children就好了。也许最好软删除它们以防我们改变主意:)
TL;DR: 是否可以将 Hibernate 配置为使用单个删除查询删除所有 child objects?
完整问题: 我在 Hibernate 5.1 中定义了以下 parent/child 关联:
public class Parent {
@OneToMany(fetch = FetchType.EAGER, mappedBy = "parent", cascade = CascadeType.REMOVE)
private List<Child> children;
}
public class Child {
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "parent_id", nullable = false)
private Parent parent;
}
当我删除 parent object 时,所有 child object 都被删除,如预期的那样,但每个都被单独删除。在我的应用程序中,一个 parent 可能有数千个 children,因此出于性能原因,我需要使用单个查询一次将它们全部删除。
可能的解决方法
- 在删除 parent 之前手动执行我自己的 HQL 查询
DELETE FROM child WHERE parent_id = ?
。这里的缺点是我(和任何其他开发人员)必须记住调用该方法。另外,它基本上绕过了级联删除。 - 允许级联删除发生在数据库级别。由于数据在幕后发生变化,我假设我需要记住手动
.clear()
child 集合以防止 Hibernate 和数据库之间的差异。
编辑: 我看到旧版本的 Hibernate 曾经有 one-shot delete 的概念,但我在最新版本的文档中找不到任何类似的内容。该功能是否已删除?
- 假设您删除了父项。
- 如果其他 table,比如 GrandChild,有外键约束 对于 Child,每个 Child 都有多个 GrandChild 记录,他们 也需要删除。
- 生成多个删除查询的原因是,Hibernate 可以 不知道有没有其他的外键约束 tables,到"Child" table。也可能有一些回调方法需要执行,例如@PreRemove。这就是为什么每个子引用都从数据库中加载并单独删除的原因。
- 简而言之,如果您依赖 Hibernate 来管理您的实体,这 是默认行为。
要么在数据库中明确设置ON DELETE CASCADE,要么标记 带有注释的所需子实体 @org.hibernate.annotations.OnDelete,它会自动添加 "on delete" 在模式生成期间添加到模式。对于您的示例,它将是,
`@OneToMany(fetch = FetchType.EAGER, mappedBy = "parent", cascade = CascadeType.REMOVE) @org.hibernate.annotations.OnDelete( action = @org.hibernate.annotations.OnDeleteAction.CASCADE) private List<Child> children;
这似乎过于简单,所以我可能没有正确理解您的问题,但是:
Parent parent = parentRepository.findByName("dad");
parent.getChildren().clear();
entityManager.save(parent);
要是我们能.clear() 我们的children就好了。也许最好软删除它们以防我们改变主意:)