Hibernate 中的级联删除:从表中删除的顺序是什么?
Cascading delete in Hibernate: What order to delete from tables?
在我的 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;
}
你做的就是所谓的bulk delete
。它是高性能的,但有一些缺点:
- 不尊重级联
- 不能使用连接(有点合乎逻辑)
您之前可以删除子实体,这是最高效的解决方案。
还有另一种解决方案,利用 Cascade
选项(实际上它是反模式,如果应该删除很多行) - 您可以遍历要删除的实体并调用 Session.delete()
每个。
更新
假设您在 Parent
和 Children
实体之间有 @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);
}
在我的 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;
}
你做的就是所谓的bulk delete
。它是高性能的,但有一些缺点:
- 不尊重级联
- 不能使用连接(有点合乎逻辑)
您之前可以删除子实体,这是最高效的解决方案。
还有另一种解决方案,利用 Cascade
选项(实际上它是反模式,如果应该删除很多行) - 您可以遍历要删除的实体并调用 Session.delete()
每个。
更新
假设您在 Parent
和 Children
实体之间有 @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);
}