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_.id=childentit1_.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();}
}

上面的代码中的方法getFirstActualTypeArgument(),getManyToOneField(),getIdField()和getOneToManyFields()并未在此处显示,但是听起来像它们的名字。 实施后,我们可以轻松删除所有以树的根开头的实体。

  • 可以在github上找到一个可用于检查上述行为和解决方案的简单示例应用程序。
参考:在Martin's Developer World博客上, 使用JPA和Hibernate从我们的JCG合作伙伴 Martin Mois 有效地删除了数据 。

翻译自: https://www.javacodegeeks.com/2013/11/efficiently-delete-data-with-jpa-and-hibernate.html

jpa和hibernate

jpa和hibernate_使用JPA和Hibernate有效删除数据相关推荐

  1. hibernate先删除数据,紧接着执行插入时的异常解决之道——中间不能调用flush()、clear()等方法...

    hibernate先删除数据,紧接着执行插入时的异常解决之道--中间不能调用flush().clear()等方法 项目中包含这样一个寻常的业务:为某一个用户指定用户群.一个用户可以被分配到多个用户群中 ...

  2. jpa和hibernate_从JPA到Hibernate的旧版和增强型标识符生成器

    jpa和hibernate JPA标识符生成器 JPA定义了以下标识符策略: 战略 描述 汽车 持久性提供程序选择基础数据库支持的最合适的标识符策略 身份 标识符由数据库IDENTITY列分配 序列 ...

  3. 使用JPA和Hibernate有效删除数据

    您可能会遇到必须对关系数据库中存储的大量数据集执行批量删除的情况. 如果您将JPA与Hibernate一起用作基础OR映射器,则可以尝试通过以下方式调用EntityManager的remove()方法 ...

  4. Hibernate、JPA、Spring Data JPA,傻傻分不清

    国庆假期接近尾声,明天最后一天了,要开始收收心啦- 今天讲讲一个初学者(或许一些老手)可能没去搞懂的几个概念:Hibernate.JPA.Spring Data JPA 之间的关联. 嘿嘿,前段时间有 ...

  5. 简述 JPA 与 Spring Data JPA 与 Hibernate

    1.JPA是什么?以及相关概述 JPA的是 Java Persistence API 的简写,是Sun官方提出的一种ORM规范! Sun提出此规范有2个原因: 1.简化现有Java EE和Java S ...

  6. JPA学习笔记2——JPA高级

    2019独角兽企业重金招聘Python工程师标准>>> 1.JPA的实体生命周期: JPA的实体有以下4中生命周期状态: (1).New:瞬时对象,尚未有id,还未和Persiste ...

  7. JPA入门到精通 - JPA入门

    为什么80%的码农都做不了架构师?>>>    概述 自己用JPA很长时间了,但没有系统学习,通过课程自学下平时比较少碰到的内容,并笔记. JPA概述 什么是JPA JPA是Java ...

  8. jpa 与非jpa 结合_EasyCriteria –使用JPA标准的简便方法

    jpa 与非jpa 结合 今天,我们将看到有关此工具的信息,该工具使使用JPA Criteria更加容易. 使用该库的应用程序将在JPA实现中更加简洁,易于使用和可移植. 在本文的结尾,您将找到要下载 ...

  9. 类型 jpa mysql_Spring Boot集成JPA

    前言 第一次使用 Spring JPA 的时候,感觉这东西简直就是神器,几乎不需要写什么关于数据库访问的代码一个基本的 CURD 的功能就出来了.下面我们就用一个例子来讲述以下 JPA 使用的基本操作 ...

最新文章

  1. 图着色问题贪心算法c语言,区间图着色问题(贪心算法)C++实现
  2. flume高可用-failover-配置文件编写
  3. 图解python pdf_Python合并同一个文件夹下所有PDF文件的方法
  4. rollup学习小记
  5. linux编译c++ 静态库,C/C++ 条件编译静态库
  6. C\C++不经意间留下的知识空白------宏
  7. JPA的单向一对多关联(oneToMany)实现示例(基于Spring Boot + JPA +MySQL,表自动维护)
  8. 对left join on and、left join on where的理解
  9. appliedzkp zkevm(13)中的Public Inputs
  10. 如何用Python操作Excel自动化办公?一个案例教会你openpyxl——图表设计和透视表
  11. Android视频直播的实现
  12. 企业邮箱怎么收发邮件,怎么保护公司邮件安全?
  13. [codeforces 1293A] ConneR and the A.R.C. Markland-N 不超时的二分/无限长数组map+桶排序
  14. [转] mongoose 之Shema
  15. [Invariance Matters: Exemplar Memory for Domain Adaptive Person Re-identification 魔改代码
  16. 本地时间(北京时间)和“GMT+8”时区时间的区别?
  17. MIT 公开课:Gilbert Strang《线性代数》课程笔记(汇总)
  18. python计算机视觉- 相机模型与参数标定
  19. 我的世界整合包 云服务器搭建方法(ECS)
  20. 将excel中的数据导入数据库

热门文章

  1. CF650E Clockwork Bomb(树上构造类问题、并查集)
  2. JSP页面EL表达式不解析
  3. Tomcat的web项目部署方式
  4. FileInputStream
  5. 从0部署一个动态网站
  6. 使用JDBCTemplate实现与Spring结合,方法公用 ——Emp实现类(EmpDaoImpl)
  7. win10打字突然变成繁体
  8. mysql5.1升级5.5_mysql数据库迁移,由版本5.1升级至5.5.29,需要注意哪些
  9. redis创建集群报错can‘t connect to node 192.168.163.203
  10. camel apache_Apache Camel 3 –新增功能前10名