JPA: DELETE WHERE 不删除子项并抛出异常

新手上路,请多包涵

由于 JPQL 查询,我正在尝试从 MOTHER 中删除大量行。

Mother 类定义如下:

 @Entity
@Table(name = "MOTHER")
public class Mother implements Serializable {

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "mother",
               orphanRemoval = true)
    private List<Child> children;
}

@Entity
@Table(name = "CHILD")
public class Child  implements Serializable {

    @ManyToOne
    @JoinColumn(name = "MOTHER_ID")
    private Mother mother;
}

如您所见, Mother 类有“children”并且在执行以下查询时:

 String deleteQuery = "DELETE FROM MOTHER WHERE some_condition";
entityManager.createQuery(deleteQuery).executeUpdate();

抛出异常:

 ERROR - ORA-02292: integrity constraint <constraint name> violated -
                   child record found

当然,我可以先选择所有要删除的对象并将它们检索到列表中,然后遍历它以删除所有检索到的对象,但这样的解决方案的性能会很糟糕!

那么有没有一种方法可以利用先前的映射来有效地删除所有 Mother 对象和所有 Child 与它们关联的对象,而无需先为 所有 子项编写查询?

原文由 Jean Logeart 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 468
2 个回答

DELETE(和 INSERT)不通过 JPQL 查询中的关系级联。这在规范中有明确的 说明

删除操作仅适用于指定类及其子类的实体。它不会级联到相关实体。

幸运的是,通过实体管理器坚持和删除(当定义了级联属性时)。

你可以做什么:

  • 获取所有应删除的母实体实例。
  • 为它们中的每一个调用 EntityManager.remove()。

代码是这样的:

 String selectQuery = "SELECT m FROM Mother m WHERE some_condition";
List<Mother> mothersToRemove = entityManager
    .createQuery(selectQuery)
    .getResultStream()
    .forEach(em::remove);

原文由 Mikko Maunu 发布,翻译遵循 CC BY-SA 4.0 许可协议

您是否尝试过使用 session.delete() 或等效的 EntityManager.remove()

当您使用 HQL delete 语句发出查询时,您可能会绕过 Hibernate 的级联机制。看看这个 JIRA 问题: HHH-368

您可能可以通过以下方式实现这一目标:

 Mother mother = session.load(Mother.class, id);
// If it is a lazy association,
//it might be necessary to load it in order to cascade properly
mother.getChildren();
session.delete(mother);

我现在不确定是否有必要初始化集合以使其正确级联。

原文由 Xavi López 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题