JPA 6.JPQL
JPQL
JPQL语言
JPQL语言,即 Java Persistence Query Language 的简称。JPQL 是一种和 SQL 非常类似的中间性和对象化查询语言,它最终会被编译成针对不同底层数据库的 SQL 查询,从而屏蔽不同数据库的差异。
JPQL语言的语句可以是 select 语句、update 语句或delete语句,它们都通过 Query 接口封装执行
javax.persistence.Query
Query接口封装了执行数据库查询的相关方法。调用 EntityManager 的 createQuery、create NamedQuery 及 createNativeQuery 方法可以获得查询对象,进而可调用 Query 接口的相关方法来执行查询操作。
Query接口的主要方法
int executeUpdate()
用于执行update或delete语句。List getResultList()
用于执行select语句并返回结果集实体列表。Object getSingleResult()
用于执行只返回单个结果实体的select语句。Query setFirstResult(int startPosition)
用于设置从哪个实体记录开始返回查询结果。Query setMaxResults(int maxResult)
用于设置返回结果实体的最大数。与setFirstResult结合使用可实现分页查询。Query setFlushMode(FlushModeType flushMode)
设置查询对象的Flush模式。参数可以取2个枚举值:FlushModeType.AUTO 为自动更新数据库记录,FlushMode Type.COMMIT 为直到提交事务时才更新数据库记录。setHint(String hintName, Object value)
设置与查询对象相关的特定供应商参数或提示信息。参数名及其取值需要参考特定 JPA 实现库提供商的文档。如果第二个参数无效将抛出IllegalArgumentException异常。setParameter(int position, Object value)
为查询语句的指定位置参数赋值。Position 指定参数序号,value 为赋给参数的值。setParameter(int position, Date d, TemporalType type)
为查询语句的指定位置参数赋 Date 值。Position 指定参数序号,value 为赋给参数的值,temporalType 取 TemporalType 的枚举常量,包括 DATE、TIME 及 TIMESTAMP 三个,,用于将 Java 的 Date 型值临时转换为数据库支持的日期时间类型(java.sql.Date、java.sql.Time及java.sql.Timestamp)。setParameter(int position, Calendar c, TemporalType type)
为查询语句的指定位置参数赋 Calenda r值。position 指定参数序号,value 为赋给参数的值,temporalType 的含义及取舍同前。setParameter(String name, Object value)
为查询语句的指定名称参数赋值。setParameter(String name, Date d, TemporalType type)
为查询语句的指定名称参数赋 Date 值。用法同前。setParameter(String name, Calendar c, TemporalType type)
为查询语句的指定名称参数设置Calendar值。name为参数名,其它同前。该方法调用时如果参数位置或参数名不正确,或者所赋的参数值类型不匹配,将抛出 IllegalArgumentException 异常。
JPQL语句
select语句用于执行查询。其语法可表示为:
- select_clause
- form_clause
- [where_clause]
- [groupby_clause]
- [having_clause]
- [orderby_clause]
select-from 子句
from 子句是查询语句的必选子句。
Select 用来指定查询返回的结果实体或实体的某些属性
From 子句声明查询源实体类,并指定标识符变量(相当于SQL表的别名)。
如果不希望返回重复实体,可使用关键字 distinct 修饰。select、from 都是 JPQL 的关键字,通常全大写或全小写,建议不要大小写混用。
查询所有实体
查询所有实体的 JPQL 查询字串很简单,例如:
select o from Order o 或 select o from Order as o关键字 as 可以省去。
标识符变量的命名规范与 Java 标识符相同,且区分大小写。
调用 EntityManager 的 createQuery() 方法可创建查询对象,接着调用 Query 接口的 getResultList() 方法就可获得查询结果集。
where 子句
JPQL也支持包含参数的查询,例如:
select o from Orders o where o.id = :myId
select o from Orders o where o.id = :myId and o.customer = :customerName
注意:参数名前必须冠以冒号(
:
),执行查询前须使用Query.setParameter(name, value)方法给参数赋值。也可以不使用参数名而使用参数的序号,例如:
select o from Order o where o.id = ?1 and o.customer = ?2
其中 ?1 代表第一个参数,?2 代表第一个参数。在执行查询之前需要使用重载方法
Query.setParameter(pos, value) 提供参数值。
Query query = entityManager.createQuery( “select o from Orders o where o.id = ?1 and o.customer = ?2” );
query.setParameter( 1, 2 );
query.setParameter( 2, “John” );
List orders = query.getResultList();
… …
查询部分属性
如果只须查询实体的部分属性而不需要返回整个实体。例如:
select o.id, o.customerName, o.address.streetNumber from Order o order by o.id执行该查询返回的不再是Orders实体集合,而是一个对象数组的集合(Object[]),集合的每个成员为一个对象数组,可通过数组元素访问各个属性。
使用 Hibernate 的查询缓存
String jpql = "FROM Customer c WHERE c.age > ?1";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());query = entityManager.createQuery(jpql).setHint(QueryHints.HINT_CACHEABLE, true);
order by子句
- order by子句用于对查询结果集进行排序。和SQL的用法类似,可以用 “asc“ 和 "desc“ 指定升降序。如果不显式注明,默认为升序。
select o from Orders o order by o.id
select o from Orders o order by o.address.streetNumber desc
select o from Orders o order by o.customer asc, o.id desc
group by子句与聚合查询
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;
… …
having子句
Having 子句用于对 group by 分组设置约束条件,用法与where 子句基本相同,不同是 where 子句作用于基表或视图,以便从中选择满足条件的记录;having 子句则作用于分组,用于选择满足条件的组,其条件表达式中通常会使用聚合函数。
例如,以下语句用于查询订购总数大于100的商家所售商品及数量:
select o.seller, o.goodId, sum(o.amount) from V_Orders o group by
o.seller, o.goodId having sum(o.amount) > 100having子句与where子句一样都可以使用参数。
子查询
- JPQL也支持子查询,在 where 或 having 子句中可以包含另一个查询。当子查询返回多于 1 个结果集时,它常出现在 any、all、exist s表达式中用于集合匹配查询。它们的用法与SQL语句基本相同。
JPQL函数
JPQL提供了以下一些内建函数,包括字符串处理函数、算术函数和日期函数。
字符串处理函数主要有:
concat(String s1, String s2):字符串合并/连接函数。
substring(String s, int start, int length):取字串函数。
trim([leading|trailing|both,] [char c,] String s):从字符串中去掉首/尾指定的字符或空格。
ower(String s):将字符串转换成小写形式。
upper(String s):将字符串转换成大写形式。
ength(String s):求字符串的长度。
locate(String s1, String s2[, int start]):从第一个字符串中查找第二个字符串(子串)出现的位置。若未找到则返回0。
算术函数主要有 abs、mod、sqrt、size 等。Size 用于求集合的元素个数。
日期函数主要为三个,即 current_date、current_time、current_timestamp,它们不需要参数,返回服务器上的当前日期、时间和时戳。
update语句
- update语句用于执行数据更新操作。主要用于针对单个实体类的批量更新
delete语句
- delete语句用于执行数据更新操作。
示例代码:
- 常用API
package com.ifox.hgx.jpa.test;import com.ifox.hgx.jpa.entity.Customer;
import com.ifox.hgx.jpa.entity.Order;
import org.hibernate.jpa.QueryHints;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;import javax.persistence.*;
import java.util.List;public class TestJPQL {private EntityManagerFactory entityManagerFactory;private EntityManager entityManager;private EntityTransaction transaction;@Beforepublic void init() {entityManagerFactory = Persistence.createEntityManagerFactory("jpa_m1");entityManager = entityManagerFactory.createEntityManager();transaction = entityManager.getTransaction();transaction.begin();}@Afterpublic void destroy() {transaction.commit();entityManager.close();entityManagerFactory.close();}//需要注意的是位置参数的是位置前加符号”?”,命名参数是名称前是加符号”:”。@Testpublic void testHelloJPQL() {// String jpql = "FROM Customer c WHERE c.age > ?1";
// Query query = entityManager.createQuery(jpql);
// query.setParameter(1, 1);String jpql = "FROM Customer c where c.age > :age";Query query = entityManager.createQuery(jpql);query.setParameter("age", 1);List<Customer> customers = query.getResultList();System.out.println(customers.size());/*** 注意:如果是双向关联的 可能会发生:StackOverflowError*/
// for (Customer customer:customers) {// System.out.println(customer);
// }}//默认情况下, 若只查询部分属性, 则将返回 Object[] 类型的结果. 或者 Object[] 类型的 List.//也可以在实体类中创建对应的构造器, 然后再 JPQL 语句中利用对应的构造器返回实体类的对象.@Testpublic void testPartlyProperties() {String jpql = "SELECT new Customer(c.lastName, c.age) FROM Customer c WHERE c.id > ?1";List result = entityManager.createQuery(jpql).setParameter(1, 1).getResultList();System.out.println(result);//输出结果:[Customer{id=null, lastName='CCC', email='null', age=34, createTime=null, birth=null, orders=[]}]}//createNamedQuery 适用于在实体类前使用 @NamedQuery 标记的查询语句//在实体类上:@NamedQuery(name = "testNameQuery" ,query = "select c from Customer c where c.age = ?1")@Testpublic void testNameQuery() {Customer customer = (Customer) entityManager.createNamedQuery("testNameQuery").setParameter(1, 34).getSingleResult();System.out.println(customer);}//createNativeQuery 适用于本地 SQL@Testpublic void test() {String sql = "select age from JPA_CUSTOMTERS where id = ?";Query query = entityManager.createNativeQuery(sql).setParameter(1, 1);int age = (int) query.getSingleResult();System.out.println("age:" + age);}//使用 hibernate 的查询缓存.@Testpublic void testQueryCache(){String jpql = "FROM Customer c WHERE c.age > ?1";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());query = entityManager.createQuery(jpql).setHint(QueryHints.HINT_CACHEABLE, true);//占位符的索引是从 1 开始query.setParameter(1, 1);customers = query.getResultList();System.out.println(customers.size());}//查询 order 数量大于 2 的那些 Customer@Testpublic 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);}@Testpublic void testOrderBy(){String jpql = "FROM Customer c WHERE c.age > ?1 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());}/*** JPQL 的关联查询同 HQL 的关联查询.** LEFT OUTER JOIN FETCH c.orders** FETCH 很关键 会自动封装类*/@Testpublic void testLeftOuterJoinFetch(){String jpql = "select c FROM Customer c LEFT OUTER JOIN FETCH c.orders WHERE c.id = ?1";Customer customer =(Customer) entityManager.createQuery(jpql).setParameter(1, 1).getSingleResult();System.out.println(customer);System.out.println(customer.getLastName());System.out.println(customer.getOrders().size());// List<Object[]> result = entityManager.createQuery(jpql).setParameter(1, 12).getResultList();
// System.out.println(result);}@Testpublic void testSubQuery(){//查询所有 Customer 的 lastName 为 YY 的 OrderString jpql = "SELECT o FROM Order o "+ "WHERE o.customer = (SELECT c FROM Customer c WHERE c.lastName = ?1)";Query query = entityManager.createQuery(jpql).setParameter(1, "KKK");List<Order> orders = query.getResultList();System.out.println(orders.size());}//使用 jpql 内建的函数@Testpublic void testJpqlFunction(){String jpql = "SELECT lower(c.email) FROM Customer c";List<String> emails = entityManager.createQuery(jpql).getResultList();System.out.println(emails);}//可以使用 JPQL 完成 UPDATE 和 DELETE 操作.@Testpublic void testExecuteUpdate(){String jpql = "UPDATE Customer c SET c.lastName = ?1 WHERE c.id = ?2";Query query = entityManager.createQuery(jpql).setParameter(1, "YYY").setParameter(2, 1);query.executeUpdate();}}
- 实现分页排序查询
public CarManagementPageDTOS page(CarManagementPageRequest pageRequest) {String jpql = "select new com.enduser.dto.CarManagementPage(ee.userName, ec.id, ec.endUserId, ec.parkedStatus,ec.plateNumber, ec.status, ecc.vin,ecc.imgUrl)" + "from com.entity.enduer.EndUserCarInfoEO ec left join EndUserCarCeEO ecc on ec.id = ecc.endUserCarInfoId left join com.entity.enduer.EndUserEO ee on ec.endUserId = ee.id where 1=1 ";//拼装条件if (pageRequest.getUserName() != null) {jpql = jpql + " and ec.endUserId in ( SELECT id FROM com.entity.enduer.EndUserEO er WHERE er.userName LIKE :userName) ";}if (pageRequest.getPlateNumber() != null) {jpql = jpql + " and ec.plateNumber like :plateNumber ";}//排序jpql = jpql + " order by ec.modifyDate DESC ";//创建jpql查询Query query = entityManager.createQuery(jpql);//设置参数if (pageRequest.getUserName() != null) {query.setParameter("userName", "%" + pageRequest.getUserName() + "%");}if (pageRequest.getPlateNumber() != null) {query.setParameter("plateNumber", "%" + pageRequest.getPlateNumber() + "%");}//得到总的记录数int totalCount = query.getResultList().size();/**public class PageDetail {//总记录数private int totalCount;//当页数量private int pageSize;//页码private int pageNo;//....*///设置分页信息PageResponseDetail pageResponseDetail = new PageResponseDetail();pageResponseDetail.setPageNo(pageRequest.getPageNo() - 1);pageResponseDetail.setPageSize(pageRequest.getPageSize());pageResponseDetail.setTotalCount(totalCount);//得到查询内容的实体List<CarManagementPageDTO> carManagementPageDTOList = query.setFirstResult((pageRequest.getPageNo() - 1) * pageRequest.getPageSize()).setMaxResults(pageRequest.getPageSize()).getResultList();/**public class CarManagementPageDTOS {//查询信息封装的实体private List<CarManagementPageDTO> carManagementPageDTOList ;//分页实体private PageResponseDetail pageResponseDetail ;//....*/CarManagementPageDTOS carManagementPageDTOS = new CarManagementPageDTOS(carManagementPageDTOList, pageResponseDetail);//封装了查询的信息,分页信息return carManagementPageDTOS;
}
JPA 6.JPQL相关推荐
- Spring Data JPA使用JPQL与原生SQL进行查询
1.使用JPQL语句进行查询 JPQL语言(Java Persistence Query Language)是一种和SQL非常类似的中间性和对象化查询语言,它最终会被编译成针对不同底层数据库的SQL语 ...
- JPA - 自定义JPQL替代JPA命名方法
目录 前言 JPQL与SQL的区别 具体应用 JPQL 语句基本格式 简单示例 前言 JPA框架通过解析方法名称的方式生成对应的SQL,极大减少了开发工作量,JPA满足于通用情况下的简单开发工作,一些 ...
- JPA(4) JPQL一些简单的查询语法
JPQL --> JPA Query Language --> JPA的查询语句 (另外HQL:Hibernate的查询语句) JPQL本质:JPA通过antlr-2.7.7.jar ...
- jpa之jpql查询
JPQL介绍 JPQL语言,即 Java Persistence Query Language 的简称.JPQL 是一种和 SQL 非常类似的中间性和对象化查询语言,它最终会被编译成针对不同底层数据库 ...
- JPA 概述及 SpringDataJpa 框架基本使用指南
概述 JPA 介绍 JPA 官方文档:传送门 JPA(Java Persistence API)是 Java 标准中的一套 ORM 规范(提供了一些编程的 API 接口,具体实现由 ORM 厂商实现, ...
- jpa vue管理系统_如何通过利用Java流获取类型安全和直观的Hibernate / JPA查询
jpa vue管理系统 大部分Java数据库应用程序都在使用Hibernate / JPA来弥合Java和SQL之间的鸿沟. 直到最近,我们还被迫将Java和JPQL混合使用,或者使用复杂的命令式标准 ...
- SpringData JPA 详解(自定义查询、分页、事务控制)
简介 SpringData JPA是 JPA的一种实现,极大的简化了JPA的开发,原始JPA的开发,需要创建实体管理工厂,使用实体管理器定义各种查询进行CRUD操作,而SpringData JPA只需 ...
- java 查询功能实现的八种方式
前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家.点击跳转到教程. 只是记录一下 1. HQL 2. Mybatis : mapper.xml 中写 sql . 3. ...
- SpringDataJPA入门就这么简单
一.SpringData入门 在上次学SpringBoot的时候,那时候的教程就已经涉及到了一点SpringData JPA的知识了.当时还是第一次见,觉得也没什么大不了,就是封装了Hibernate ...
最新文章
- 避不开的算法,如何吃透?
- Java加载词向量_W2C得到词向量之后,如何得到句子向量,
- activity中fragment 返回键不退出_优雅地处理加载中(loading),重试(retry)和无数据(empty)等...
- 一句话实现php日期转中文汉字
- Spring| BeanCurrentlyInCreationException: Error creating bean with name ‘‘xxx“
- qt扫雷鼠标c语言中文网,基于C语言实现的扫雷游戏代码
- 令人泪目 浙江江山古稀老人照顾俩脑瘫儿近半世纪
- 寻找相同的乱序字符串
- nettry 入站事件如何传递到下一个handler
- 计算机网络复习-数据链路层
- 产品专利和方法专利对比分析
- 手机的1G,2G,3G和4G区别识记
- 考研英语作文—谋篇布局
- MAC直接的剪切快捷键
- HDU6438-Buy and Resell(贪心、思维题)
- 在Windows 7和Vista中禁用程序兼容性助手
- c语言西华大学陈晓亮,计算机与软件工程学院
- KindEditor实现多图片上传
- Modelsim仿真操作指导
- 如何使用TensorRT加速深度学习推理