正规的网站建设企业网站制作,平度做网站公司,广告联盟怎么加入,百色优惠welcomejpa和hibernate您可能会遇到必须对关系数据库中存储的大量数据集执行批量删除的情况。 如果您将JPA与Hibernate一起用作基础OR映射器#xff0c;则可以尝试通过以下方式调用EntityManager的remove#xff08;#xff09;方法#xff1a; public void removeById(long id) … jpa和hibernate 您可能会遇到必须对关系数据库中存储的大量数据集执行批量删除的情况。 如果您将JPA与Hibernate一起用作基础OR映射器则可以尝试通过以下方式调用EntityManager的remove方法 public void removeById(long id) {RootEntity rootEntity entityManager.getReference(RootEntity.class, id);entityManager.remove(rootEntity);
} 首先我们加载要删除的实体的引用表示形式然后将此引用传递给EntityManager。 假设上面的RootEntity与名为ChildEntity的类有子关系 OneToMany(mappedBy rootEntity, fetch FetchType.EAGER, cascade CascadeType.ALL)
private Set childEntities new HashSet(0); 如果现在打开hibernate的属性show_sql我们将想知道发出什么SQL语句 selectrootentity0_.id as id5_1_,rootentity0_.field1 as field2_5_1_,rootentity0_.field2 as field3_5_1_,childentit1_.PARENT as PARENT5_3_,childentit1_.id as id3_,childentit1_.id as id4_0_,childentit1_.field1 as field2_4_0_,childentit1_.field2 as field3_4_0_,childentit1_.PARENT as PARENT4_0_fromROOT_ENTITY rootentity0_left outer joinCHILD_ENTITY childentit1_on rootentity0_.idchildentit1_.PARENTwhererootentity0_.id?deletefromCHILD_ENTITYwhereid?deletefromROOT_ENTITYwhereid? 为什么Hibernate首先将所有数据加载到内存中以便随后立即删除该数据 原因是JPA的生命周期要求对象处于“托管”状态然后才能删除它。 仅在这种状态下所有生命周期功能如拦截器才可用请参阅此处 。 因此Hibernate在删除之前发出SELECT查询以便将RootEntity和ChildEntity都转移到“托管”状态。 但是如果我们只想删除RootEntity和ChildEntity并且知道RootEntity的ID该怎么办 答案是使用类似于以下内容的简单DELETE查询。 但是由于子表的完整性约束我们首先必须删除所有依赖的子实体。 以下代码演示了如何 List childIds entityManager.createQuery(select c.id from ChildEntity c where c.rootEntity.id :pid).setParameter(pid, id).getResultList();
for(Long childId : childIds) {entityManager.createQuery(delete from ChildEntity c where c.id :id).setParameter(id, childId).executeUpdate();
}
entityManager.createQuery(delete from RootEntity r where r.id :id).setParameter(id, id).executeUpdate(); 上面的代码通过调用remove产生了我们期望的三个SQL语句。 现在您可能会说这种删除方式比仅调用EntityManager的remove方法更为复杂。 它还会忽略我们在两个实体类中放置的注释例如OneToMany和ManyToOne。 那么为什么不编写一些代码来使用关于两个类文件中已经存在的两个实体的知识呢 首先我们在RootEntity类中使用反射查找OneToMany批注提取子实体的类型然后查找其后向字段并用ManyToOne批注。 完成此操作后我们可以以更通用的方式轻松编写三个SQL语句 public void delete(EntityManager entityManager, Class parentClass, Object parentId) {Field idField getIdField(parentClass);if (idField ! null) {List oneToManyFields getOneToManyFields(parentClass);for (Field field : oneToManyFields) {Class childClass getFirstActualTypeArgument(field);if (childClass ! null) {Field manyToOneField getManyToOneField(childClass, parentClass);Field childClassIdField getIdField(childClass);if (manyToOneField ! null childClassIdField ! null) {List childIds entityManager.createQuery(String.format(select c.%s from %s c where c.%s.%s :pid, childClassIdField.getName(), childClass.getSimpleName(), manyToOneField.getName(), idField.getName())).setParameter(pid, parentId).getResultList();for (Long childId : childIds) {entityManager.createQuery(String.format(delete from %s c where c.%s :id, childClass.getSimpleName(), childClassIdField.getName())).setParameter(id, childId).executeUpdate();}}}}entityManager.createQuery(String.format(delete from %s e where e.%s :id, parentClass.getSimpleName(), idField.getName())).setParameter(id, parentId).executeUpdate();}
} 上面的代码中的方法getFirstActualTypeArgumentgetManyToOneFieldgetIdField和getOneToManyFields并未在此处显示但是听起来像它们的名字。 实施后我们可以轻松删除所有以树的根开头的实体。 可以在github上找到一个可用于检查上述行为和解决方案的简单示例应用程序。 参考在Martins Developer World博客上 使用JPA和Hibernate从我们的JCG合作伙伴 Martin Mois 有效地删除了数据 。 翻译自: https://www.javacodegeeks.com/2013/11/efficiently-delete-data-with-jpa-and-hibernate.htmljpa和hibernate