JPQL-Query查询实例详解

article/2025/10/13 19:58:54

前面学习了JPQL语言和Query接口。这里学习一下如果通过JPQL和Query接口进行数据的查询、更新和删除。

【1】普通查询

首先说明一下FROM子句和Select…FROM。

  • from 子句是查询语句的必选子句。

  • Select 用来指定查询返回的结果实体或实体的某些属性。

  • From 子句声明查询源实体类,并指定标识符变量(相当于SQL表的别名)。

如果不希望返回重复实体,可使用关键字 distinct 修饰。select、from 都是 JPQL 的关键字,通常全大写或全小写,建议不要大小写混用。

代码实例如下:

@Test
public void testHelloJPQL(){String jpql = "select c FROM Customer c WHERE c.age > ?";Query query = (Query) entityManager.createQuery(jpql);//占位符的索引是从 1 开始query.setParameter(1, 1);List<Customer> customers = query.getResultList();System.out.println(customers.size());
}

控制台输出如下:

这里写图片描述

可以看到就是一条普通的查询语句。

但是在写JPQL时,需要注意,这一切面向对象。即对象+属性相当于表+列,可以联想一下Hibernate的HQL语言。

如果不写 select 而是直接使用from子句,表明获取对象的全部属性。

String jpql = FROM Customer c WHERE c.age > ?;

需要注意的是查询一个对象的所有属性时,并不能像MySQL那样使用 * 号标志。下面语句是错误的,不符合JPQL的规范。

select * FROM Customer c WHERE c.age > ?

当然,你可以查询部分属性

默认情况下, 若只查询部分属性, 则将返回 Object[] 类型的结果. 或者 Object[] 类型的 List。
.
也可以在实体类中创建对应的构造器, 然后再 JPQL 语句中利用对应的构造器返回实体类的对象.

代码实例如下:

@Test
public void testPartlyProperties(){String jpql = "SELECT c.lastName, c.age FROM Customer c WHERE c.id > ?";List result = entityManager.createQuery(jpql).setParameter(1, 1).getResultList();System.out.println(result);Object[] objects = (Object[]) result.get(0);System.out.println(objects[0]);
}

控制台输出如下:

这里写图片描述

可以看到,获取到的list是一个list<object[]>,解析起来是比较麻烦的。故而,我们更希望使用如下方式:

@Test
public void testPartlyProperties(){String jpql = "SELECT new Customer(c.lastName, c.age) FROM Customer c WHERE c.id > ?";List result = entityManager.createQuery(jpql).setParameter(1, 1).getResultList();System.out.println(result);}

控制台输出如下:

这里写图片描述

这样获取到的是list<Customer>,这样解析起来就很友好了。

【2】createNamedQuery和createNativeQuery

① createNamedQuery 适用于在实体类前使用 @NamedQuery 标记的查询语句。

代码示例如下:

@NamedQuery(name="testNamedQuery", query="FROM Customer c WHERE c.id = ?")
@Cacheable(true)
@Table(name="jpa_cutomers")
@Entity
public class Customer {private Integer id;private String lastName;private String email;private int age;private Date createdTime;private Date birth;public Customer() {}
//...
}

测试代码实例如下:

@Test
public void testNamedQuery(){Query query = entityManager.createNamedQuery("testNamedQuery").setParameter(1, 3);Customer customer = (Customer) query.getSingleResult();System.out.println(customer);
}

控制台输出如下:

这里写图片描述

② createNativeQuery 适用于本地 SQL

即,你可以像MySQL那样写sql语句进行查询。

代码实例如下:

@Test
public void testNativeQuery(){String sql = "SELECT age FROM jpa_cutomers WHERE id = ?";Query query = entityManager.createNativeQuery(sql).setParameter(1, 3);Object result = query.getSingleResult();System.out.println(result);
}

控制台输出如下:

这里写图片描述

【3】(Hibernate)查询缓存

什么是查询缓存?参考博文Hibernate查询缓存应用实例

① 不使用查询缓存

多次查询同条语句,代码实例如下:

@Test
public void testQueryCache(){
String jpql = "FROM Customer c WHERE c.age > ?";
Query query = entityManager.createQuery(jpql);//占位符的索引是从 1 开始
query.setParameter(1, 1);
List<Customer> customers = query.getResultList();
System.out.println(customers.size());query = entityManager.createQuery(jpql);
//占位符的索引是从 1 开始
query.setParameter(1, 1);
customers = query.getResultList();
System.out.println(customers.size());
}

控制台输出如下:

这里写图片描述

② 使用查询缓存

persistence.xml配置如下:

<!-- 二级缓存相关 -->
<property name="hibernate.cache.use_second_level_cache" value="true"/>
<property name="hibernate.cache.region.factory_class" value="org.hibernate.cache.ehcache.EhCacheRegionFactory"/>
<!--  这里表明使用查询缓存 -->
<property name="hibernate.cache.use_query_cache" value="true"/>

代码实例如下:

@Test
public void testQueryCache(){String jpql = "FROM Customer c WHERE c.age > ?";// QueryHints.HINT_CACHEABLE设置为trueQuery query = entityManager.createQuery(jpql).setHint(QueryHints.HINT_CACHEABLE, true);//占位符的索引是从 1 开始query.setParameter(1, 1);List<Customer> customers = query.getResultList();System.out.println(customers.size());query = entityManager.createQuery(jpql).setHint(QueryHints.HINT_CACHEABLE, true);//占位符的索引是从 1 开始query.setParameter(1, 1);customers = query.getResultList();System.out.println(customers.size());
}

控制台输出如下:

这里写图片描述

【4】更新和删除

JPQL的更新和删除主要 用的是query.executeUpdate()方法;

代码实例如下:

@Test
public void testExecuteUpdate(){String jpql = "UPDATE Customer c SET c.lastName = ? WHERE c.id = ?";Query query = entityManager.createQuery(jpql).setParameter(1, "YYY").setParameter(2, 12);query.executeUpdate();
}

控制台输出如下:

这里写图片描述

删除同上。

【5】order by,group by 和having子句

JPQL是面向对象的,和hibernate一致。此外,像排序、分组等和普通MySQL并无差异。

group by 子句用于对查询结果分组统计,通常需要使用聚合函数。

常用的聚合函数主要有 AVG、SUM、COUNT、MAX、MIN 等,它们的含义与SQL相同。

例如:

select max(o.id) from Orders o

没有 group by 子句的查询是基于整个实体类的,使用聚合函数将返回单个结果值,可以使用Query.getSingleResult()得到查询结果。

例如:

Query query = entityManager.createQuery("select max(o.id) from Orders o");
Object result = query.getSingleResult();
Long max = (Long)result;

group by实例:

//查询 order 数量大于 2 的那些 Customer
@Test
public void testGroupBy(){String jpql = "SELECT o.customer FROM Order o "+ "GROUP BY o.customer "+ "HAVING count(o.id) >= 2";List<Customer> customers = entityManager.createQuery(jpql).getResultList();System.out.println(customers);
}

Having 子句用于对 group by 分组设置约束条件,用法与where 子句基本相同。

不同是 where 子句作用于基表或视图,以便从中选择满足条件的记录;having 子句则作用于分组,用于选择满足条件的组,其条件表达式中通常会使用聚合函数。


order by 实例:

@Test
public void testOrderBy(){String jpql = "FROM Customer c WHERE c.age > ? ORDER BY c.age DESC";Query query = entityManager.createQuery(jpql).setHint(QueryHints.HINT_CACHEABLE, true);//占位符的索引是从 1 开始query.setParameter(1, 1);List<Customer> customers = query.getResultList();System.out.println(customers.size());
}

order by子句用于对查询结果集进行排序。和SQL的用法类似,可以用 “asc“ 和 "desc“ 指定升降序。

如果不显式注明,默认为升序。

【6】关联查询与Fetch

在JPQL中,很多时候都是通过在实体类中配置实体关联的类属性来实现隐含的关联(join)查询。

例如:

select o from Orders o where o.address.streetNumber=2000 

上述JPQL语句编译成以下SQL时就会自动包含关联,默认为左关联。

在某些情况下可能仍然需要对关联做精确的控制。为此,JPQL 也支持和 SQL 中类似的关联语法。

如:

left out join / left join 
inner join 
left join / inner join fetch 

其中,left join和left out join等义,都是允许符合条件的右边表达式中的实体为空。

左外连接实例如下:

@Test
public void testLeftOuterJoinFetch(){String jpql = "FROM Customer c LEFT OUTER JOIN FETCH c.orders WHERE c.id = ?";Customer customer = (Customer) entityManager.createQuery(jpql).setParameter(1, 7).getSingleResult();System.out.println(customer.getLastName());System.out.println(customer.getOrders().size());
}

控制台输出如下:

这里写图片描述

需要注意的是,这里JPQL用到了FETCH。如果不加FETCH呢?

代码实例如下:

@Test
public void testLeftOuterJoinFetch(){String jpql = "FROM Customer c LEFT OUTER JOIN  c.orders WHERE c.id = ?";List<Object[]> result = entityManager.createQuery(jpql).setParameter(1, 7).getResultList();System.out.println(result);
}

控制台输出如下:

这里写图片描述

“fetch”连接允许仅仅使用一个选择语句就将相关联的对象或一组值的集合随着他们的父对象的初始化而被初始化。

在默认的查询中,Entity中的集合属性默认不会被关联,集合属性默认是延迟加载( lazy-load )。那么,left fetch/left out fetch/inner join fetch提供了一种灵活的查询加载方式来提高查询的性能。

综上,在使用JPQL语言时 ,需要时刻记得和hibernate一致–面向对象。如果你使用的Query为createNativeQuery,才可以像使用普通MySQL一样进行数据操作。

【7】子查询

JPQL也支持子查询,在 where 或 having 子句中可以包含另一个查询。

当子查询返回多于 1 个结果集时,它常出现在 any、all、exist s表达式中用于集合匹配查询。

它们的用法与SQL语句基本相同。

子查询实例如下:

@Test
public void testSubQuery(){//查询所有 Customer 的 lastName 为 YY 的 OrderString jpql = "SELECT o FROM Order o "+ "WHERE o.customer = (SELECT c FROM Customer c WHERE c.lastName = ?)";Query query = entityManager.createQuery(jpql).setParameter(1, "YY");List<Order> orders = query.getResultList();System.out.println(orders.size());
}

控制台输出如下:

这里写图片描述


http://chatgpt.dhexx.cn/article/yl9lK769.shtml

相关文章

JPQL和SQL的比较

前言 在JAVA EE中&#xff0c;JPQL是专门为Java 应用程序访问和导航实体实例设计的。Java Presistence Query Language(JPQL)&#xff0c;java持久性查询语言。它是JPA规范的重要组成部分&#xff0c;其实它就是一种查询语言&#xff0c;语法类似于SQL语法&#xff0c;但是有着…

【JPQL】--JPQL和SQL的比较

前言 在JAVA EE中&#xff0c;JPQL是专门为Java 应用程序访问和导航实体实例设计的。Java Presistence Query Language(JPQL)&#xff0c;java持久性查询语言。它是JPA规范的重要组成部分&#xff0c;其实它就是一种查询语言&#xff0c;语法类似于SQL语法&#xff0c;但是有着…

JPA - JPQL完成复杂的多表查询

目录 前言示例建表语句Entity实体JPQL多表查询完整代码调用结果 前言 JPA中可以通过设置实体的导航属性 JPQL完成复杂的多表查询&#xff0c;简化SQL的编写。 示例 建表语句 Table CREATE TABLE school (id int(11) DEFAULT NULL,name varchar(50) COLLATE utf8_unicode_c…

JPQL查询

JPQL查询 1 jpql的介绍 sql&#xff1a;查询的是表和表中的字段。 jpql&#xff1a;查询的是实体类和类中的属性。 jpql和sql语句的语法相似。 JPQL全称Java Persistence Query Language 基于首次在EJB2.0中引入的EJB查询语言(EJB QL),Java持久化查询语言(JPQL)是一种可移植的…

JPQL详解

前提 最近在改bug的时候发现了自己的缺点&#xff0c;在改前端bug的时候非常顺利顺手。但是在改后端bug的时候如果遇到不是太难的问题还可以解决&#xff0c;但是一到难点感觉自己就懵逼&#xff01; 所以讲解了关于JPQl相关内容 JPA 在说jpql之前必须要说一下什么是JPA&…

JPA(4) JPQL一些简单的查询语法

JPQL --> JPA Query Language --> JPA的查询语句 (另外HQL:Hibernate的查询语句) JPQL本质&#xff1a;JPA通过antlr-2.7.7.jar将JPQL编译成sql并且封装执行的。 JPQL和SQL区别&#xff1f;&#xff1f; --> 它们查询的关键字都是一样的&#xff…

HPROF内存文件获取

1.命令生成Dump内存文件 命令&#xff1a;am dumpheap 进程名 输出文件目录<文件名.hprof> 如&#xff1a; am dumpheap app …/demo.hprof 2.通过Android Studio获取 在Android Studio中使用Android Monitor里的Memory Monitor工具监视内存使用情况时&#xff0c;可以…

jvm调优-hprof 文件打开

当服务器出现内存溢出的情况&#xff0c;要下载分析dump内存文件“ dump 当前进程的内存信息: 通过命令 jsp获取java进程pid: jsp: 生成dump文件&#xff1a; jmap -dump:formatb,filedump.hprof pid在当前目录xiazaihprof文件到本地。 如何打开hprof后缀格式的文件呢&#…

使用adb命令导出hprof文件

我们可以使用android studio profiler导入hprof文件分析android应用的内存问题。那么如何从手机上面导出这份文件呢&#xff1f; 把应用的heap 区的数据取出来保存在一个hprof文件上&#xff0c;然后把hprof文件导入到可以查看这个文件的工具上&#xff08;如android studio p…

jvisualvm分析hprof文件

jvisualvm是jdk8的bin目录下自带的一个分析工具&#xff0c;在我下载的jdk11下没有这个工具&#xff0c;这个工具我们可以用来分析hprof文件 首先我们可以配置对应的参数&#xff0c;配置文件地址在\jdk8\lib\visualvm\etc\visualvm.conf visualvm_default_options"-J-cl…

android studio 分析 hprof,Android Studio 中的 HProf静态分析

HProf 在 Android Studio 中的展示详解&#xff0c;基于我对其的理解&#xff0c;我将其根据 heap,count,size,其他将其分成了 4 个层次。 第一层 Heap 分类 Heap 共分为&#xff1a; zygote heap: 与 android zygote 进程共享的 heap image heap: 与系统共享的 heap app heap&…

JProfile 分析OOM hprof文件

JProfile 分析OOM OutOfMemoryError 1.JVM组成 首先要明白JVM组成 方法区-非堆 Method Area、No-HeapJava栈-虚拟机栈 VM Stack、Java Stack本地方法栈 Native Method Stack程序计数器 Program Counter Register堆 Heap 1.1 OOM发生在哪里? OOM可以发生在除了程序计数器外…

java如何打开hprof_hprof是什么文件?如何打开hprof?

hprof是什么文件&#xff1f;如何打开hprof&#xff1f; 发布时间&#xff1a;2020-03-26 17:35:24 来源&#xff1a;亿速云 阅读&#xff1a;1195 作者&#xff1a;小新 hprof是什么文件&#xff1f;如何打开hprof&#xff1f;很多人都不太了解&#xff0c;今天小编为了让大家…

linux命令生成hprof文件,Android平台生成任意进程的hprof文件

一、知识介绍 1.1 为什么要抓取hprof hprof文件中记录了当前进程内存的使用情况,对于一些难以解决的OOM问题,提取出对应进程的hprof文件可以很好的分析这种问题。 分析hprof的工具 Java Heap Analyzes Tool Eclipse Memory Analyzer 1.2 生成hprof指令 adb shell am dumpheap…

java hprof文件_JVM性能调优监控工具hprof使用详解

一、问题现状 现实企业级Java开发中,有时候我们会碰到下面这些问题: OutOfMemoryError,内存不足 内存泄露 线程死锁 锁争用(Lock Contention) Java进程消耗CPU过高 …… 这些问题在日常开发中可能被很多人忽视(比如有的人遇到上面的问题只是重启服务器或者调大内存,而不会深…

java hprof文件_hprof是什么文件

hprof是什么文件&#xff1f; 是java进程的内存镜像文件&#xff0c;里面包含了内存堆详细的使用信息。 最近学习深入java虚拟机的书&#xff0c;照着里面的例子跑了下。 如何打开hprof&#xff1f; 下面是demo&#xff1a;/** * VM Args&#xff1a;-Xms20m -Xmx20m -XX:HeapD…

Hprof

转载地址&#xff1a;http://geek.csdn.net/news/detail/90509 一、开发者的自测利器-Hprof命令 1. 示例演示 例子程序&#xff1a; /*** PROJECT_NAME: test* DATE: 16/7/22* CREATE BY: chao.cheng**/ public class HProfTest {public void slowMethod() {try {T…

android hprof,Android Hprof 分析

Android Studio 中的 HProf静态分析 HProf 在 Android Studio 中的展示详解&#xff0c;基于我对其的理解&#xff0c;我将其根据 heap,count,size,其他将其分成了 4 个层次。 第一层 Heap分类 Heap 共分为&#xff1a; zygote heap: 与 android zygote 进程共享的 heap image …

android中hprof文件分析

Hprof基本概念 hprof最初是由J2SE支持的一种二进制堆转储格式&#xff0c;hprof文件保存了当前java堆上所有的内存使用信息&#xff0c;能够完整的反映虚拟机当前的内存状态。 格式 Hprof文件由FixedHead和一系列的Record组成&#xff0c;Record包含字符串信息、类信息、栈信…

hprof 文件查看

https://www.jianshu.com/p/4e6e88f1d211 hprof 文件是 Java 的 内存快照文件&#xff08;Heap Profile 的缩写&#xff09;&#xff0c;格式为 java_pid*.hprof 用于分析 OOM: OutOfMemoryError(堆)内存不足错误 是 JVM 设置 -XX:HeapDumpOnOutOfMemoryError 参数时打印的内容…