一尘不染

JPA:DELETE WHERE不会删除子项并引发异常

hibernate

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

所述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该类具有“子级”,并且在执行以下查询时:

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对象,而无需先为 所有 子对象编写查询?


阅读 396

收藏
2020-06-20

共1个答案

一尘不染

删除(和INSERT)不会通过JPQL查询中的关系进行级联。这在规范中显然是拼写的:

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

幸运的是,持久化并通过实体管理器删除(当定义了层叠属性时)。

你可以做什么:

  • 获取所有应删除的母亲实体实例。
  • 对于每个对象,请调用EntityManager.remove()。

代码是这样的:

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