有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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

在我的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.

我需要先删除所有子表吗?我认为cascade delete背后的想法是,它自动执行此操作

代码:

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) 个答案

  1. # 1 楼答案

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

    • 不尊重级联
    • 无法使用联接(有些逻辑)

    您可以先删除子实体,这将是最有效的解决方案

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

    更新

    假设ParentChildren实体之间存在@OneToMany关联,您只需请求所有受影响的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);
    }