Hibernate中的级联删除:从表中删除的顺序是什么?

时间:2016-02-19 14:13:43

标签: java oracle hibernate cascade

在我的Java应用程序中,我试图在有子节点的父对象上运行cascade delete

当我运行应用程序时,我收到以下错误:

java.sql.SQLIntegrityConstraintViolationException: ORA-02292: integrity constraint  violated - child record found

我搜索过此错误,并here表明它是由于:

You tried to DELETE a record from a parent table (as referenced by a foreign key), but a record in the child table exists.

我是否需要先删除所有子表 ?我认为级联删除背后的想法是它自动执行

代码:

EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("myclasses");
                EntityManager em = entityManagerFactory.createEntityManager();
                Session session = em.unwrap(Session.class);

    Transaction transaction = session.beginTransaction();
            try {

               String hqlDelete = "DELETE FROM product WHERE price='PRICED'";
                Query queryDelete = session.createQuery(hqlDelete);
                queryDelete.executeUpdate();

               transaction.commit();
            } catch (Throwable t) {
                transaction.rollback();
                throw t;
            }

1 个答案:

答案 0 :(得分:3)

你所做的就是所谓的bulk delete。它具有高性能,但有一些缺点:

  • 不尊重级联
  • 不能使用连接(有些逻辑)

您之前可以删除子实体,什么是最高性能的解决方案。

还有另一种解决方案,即使用Cascade选项(如果应该删除许多行,实际上它是反模式) - 您可以迭代要删除的实体并调用Session.delete()每个

更新

假设@OneToManyParent实体之间存在Children关联,您可以直接询问受影响的所有Children并事先将其删除:

session
  .createQuery("DELETE FROM Children c WHERE EXISTS (SELECT p FROM Parent p WHERE p.price='PRICED' AND c IN p.children)")
  .executeUpdate();

然后,您可以安全地删除Parent个实体:

session
  .createQuery("DELETE FROM Parent p WHERE p.price='PRICED'")
  .executeUpdate();

更简洁,但性能较差的方法是查询要删除的所有Parent个实体,然后手动删除它们:

List<Parent> parents = session
  .createQuery("SELECT p FROM Parent p WHERE p.price='PRICED'");
for (Parent parent : parents) {
    session.delete(parent);
}