jpa和hibernate_使用JPA和Hibernate有效删除数据

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/346020.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

超越函数

代数数 在数论中,超越数是指任何一个不是代数数的数字(通常它是复数)。它满足以下条件——只要它不是任何一个整系数代数方程的根,它即是超越数。最著名的超越数是e以及π。 超越数 超越数的例子 所有超越数构成的集是一个不可数…

无服务器-仅仅是构建现代应用程序的一种方法?

如果搜索“无服务器”,则会发现无服务器是构建现代应用程序的一种新的流行方式。 无服务器真的是新的吗? 无服务器是指您无需担心服务器的概念-无需置备,部署和维护服务器。 显然有服务器,但是您无需考虑或担心它们,运…

linux查看用户的操作记录,Linux下查看用户登陆后的操作记录

Linux下查看用户登陆后的操作记录  在linux系统的环境下,不管是root用户还是其它的用户只有登陆系统后用进入操作我们都可以通过命令history来查看历史记录,可是假如一台 服务器多人登陆,一天因为某人误操作了删除了重要的数据。这时候通过…

只需5分钟即可启动并运行分层架构:: Spring Boot第1部分

这是一个分为两部分的系列,其中我将展示如何使用Spring Boot创建分层架构。 什么是分层体系结构:简而言之,当我们构建企业应用程序时,我们维护不同的层以封装特定于层的逻辑,这样就不会溢出到另一层。 当我们考虑企业…

机器学习算法、深度学习算法涉及的数学知识

微积分基础 导数的定义 左导数、右导数、可导函数 导数几何意义、物理意义 基本函数求导公式 四则运算法则 复合函数求导法则 神经网络激活函数的导函数求解 高阶导数 导数与函数单调性 极值定理 导数与函数凹凸性 一元函数泰勒展开 线性代数基础 向量与其运算 行向量和列向…

linux设置默认的首页文件,Linux 设置Firefox主页

Linux 设置Firefox主页在Linux系统中,当用户启动Firefox主页时,会自动打开Firefox默认设置的主页。当然,用户也可以通过Firefox的首选项,手动将Firefox主页设置为自己喜欢的或经常访问的网页。在本单元练习中,将Firefo…

spring 2.2 改进_Spring 4中@ControllerAdvice的改进

spring 2.2 改进在Spring 4的许多新功能中,我发现了ControllerAdvice的改进。 ControllerAdvice是Component的特殊化,用于定义适用于所有RequestMapping方法的 ExceptionHandler, InitBinder和ModelAttribute方法。 在Spring 4之前&#xff0…

向量范数与矩阵范数

一、向量的范数 1.1 定义 1.2 举例 首先定义一个向量为:a[-5,6,8, -10] 1.2.1 向量的1范数 向量的1范数即:向量的各个元素的绝对值之和,上述向量a的1范数结果就是:29,MATLAB代码实现为&…

不同磁盘目录共享linux,linux下实现磁盘共享(mount)

准备两台centos6.6 A(192.168.199.2)、B(192.168.199.3),A做服务端、B做客户端。一台ubuntu14.04 C(192.168.199.4)C做客户端。A、B安装nfs对应服务yum -y install nfs-utils rpcbind####C安装nfs-kernel-serverapt-get install nfs-kernel-server####A设置nfs、por…

苹果linux桌面文件夹,Ubuntu 10.04下一键安装Mac OS X主题桌面

不久前的《Ubuntu 10.04下Mac OS X风格桌面美化安装》遭到网友的砖头,认为和Mac OS X风格桌面美化安装根本没有关系。本来是要跟这篇一起发布的,一等就等了这么长,下面我们来看下在Ubuntu 10.04下一键安装Mac OS X主题桌面的工具Epidermis th…

示性函数、共轭函数、对偶范数、共轭

示性函数(Indicator function) 共轭函数 对偶范数 几个常用公式 共轭(conjugate) 所谓“轭”,指的是古代牛车上放在并行的牛脖颈上的曲木。共轭关系,通俗来说一般用以描述两件事物以一定规律相互配对或孪生(一般共轭对…

Redis-实践知识

转自极客时间Redis 亚风 原文视频:https://u.geekbang.org/lesson/535?article681062 Redis最佳实践 普通KEY Redis 的key虽然可以自定义,但是最好遵循下面几个实践的约定: 格式:[业务名称]:[数据名]:[id] 长度不超过44字节 不…

MicroProfile OpenAPI上的Swagger UI

MicroProfile OpenApi为我们提供了一种使用OpenApi 3描述我们JAX-RS API的标准化方法。如果您以前使用过swagger-jaxrs和swagger-annotations ,由于OpenApi是基于Swagger构建的,因此您会感到非常熟悉。 2015年11月5日,SmartBear与3Scale&…

linux 跟踪内存,用strace跟踪malloc内存分配

strace介绍strace是一个非常有用的命令,它用于记录和跟踪程序运行期间收到的信号和调用的系统调用。strace的简单使用ubuntu64:~$ strace cat /dev/nullexecve("/bin/cat", ["cat", "/dev/null"], [/* 32 vars */]) 0brk(NULL) 0x1…

归一化、标准化和正则化

归一化 Normalization 归一化一般是将数据映射到指定的范围,用于去除不同维度数据的量纲以及量纲单位。 常见的映射范围有 [0, 1] 和 [-1, 1] ,最常见的归一化方法就是 Min-Max 归一化: 举个例子,我们判断一个人的身体状况是否健…

slf4j绑定器_用于ADFLogger的SLF4J绑定–缺少的部分

slf4j绑定器由于最好的原因,在我的日常工作中,我希望为ADF Logger Oracle ADF提供一个SLF4J适配器。 毫不奇怪,slf4j没有用于ADFLogger的适配器,但是由于ADFLogger只是Java Util Logging的轻巧包装,因此花了一个多小时…

核心网

在我们正式讲解之前,我想通过这张网络简图帮助大家认识一下全网的网络架构,通过对全网架构的了解,将方便您对后面每一块网络细节的理解。 这张图分为左右两部分,右边为无线侧网络架构,左边为固定侧网络架构。 无线侧…

linux服务器防端口扫描,linux下防止syn***,端口扫描和死亡之ping

http://downloads.sourceforge.net ... les-v0.0.3-3.tar.gz下载以后安装:tar zxvf arptables-v0.0.3-3.tar.gzcd arptables-v0.0.3-3/makemake install生成的命令是/usr/local/sbin/arptables、/usr/local/sbin/arptables-save、/usr/local /sbin/arptables-restor…

JDK 11:轻松取出单文件Java源代码程序

JDK 11 Early Access Builds包含与JEP 330相关的预览功能(“启动单个文件源代码程序”)。 我之前在“ Shebang即将来到Java? ”和“ 为JDK 11提议的JEP 329和JEP 330 ”,由于JDK 11 Early Access Builds,在这篇文章中…