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) > 100

  • having子句与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相关推荐

  1. Spring Data JPA使用JPQL与原生SQL进行查询

    1.使用JPQL语句进行查询 JPQL语言(Java Persistence Query Language)是一种和SQL非常类似的中间性和对象化查询语言,它最终会被编译成针对不同底层数据库的SQL语 ...

  2. JPA - 自定义JPQL替代JPA命名方法

    目录 前言 JPQL与SQL的区别 具体应用 JPQL 语句基本格式 简单示例 前言 JPA框架通过解析方法名称的方式生成对应的SQL,极大减少了开发工作量,JPA满足于通用情况下的简单开发工作,一些 ...

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

    JPQL --> JPA Query Language --> JPA的查询语句    (另外HQL:Hibernate的查询语句) JPQL本质:JPA通过antlr-2.7.7.jar ...

  4. jpa之jpql查询

    JPQL介绍 JPQL语言,即 Java Persistence Query Language 的简称.JPQL 是一种和 SQL 非常类似的中间性和对象化查询语言,它最终会被编译成针对不同底层数据库 ...

  5. JPA 概述及 SpringDataJpa 框架基本使用指南

    概述 JPA 介绍 JPA 官方文档:传送门 JPA(Java Persistence API)是 Java 标准中的一套 ORM 规范(提供了一些编程的 API 接口,具体实现由 ORM 厂商实现, ...

  6. jpa vue管理系统_如何通过利用Java流获取类型安全和直观的Hibernate / JPA查询

    jpa vue管理系统 大部分Java数据库应用程序都在使用Hibernate / JPA来弥合Java和SQL之间的鸿沟. 直到最近,我们还被迫将Java和JPQL混合使用,或者使用复杂的命令式标准 ...

  7. SpringData JPA 详解(自定义查询、分页、事务控制)

    简介 SpringData JPA是 JPA的一种实现,极大的简化了JPA的开发,原始JPA的开发,需要创建实体管理工厂,使用实体管理器定义各种查询进行CRUD操作,而SpringData JPA只需 ...

  8. java 查询功能实现的八种方式

    前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家.点击跳转到教程. 只是记录一下 1. HQL 2. Mybatis : mapper.xml 中写 sql . 3. ...

  9. SpringDataJPA入门就这么简单

    一.SpringData入门 在上次学SpringBoot的时候,那时候的教程就已经涉及到了一点SpringData JPA的知识了.当时还是第一次见,觉得也没什么大不了,就是封装了Hibernate ...

最新文章

  1. 避不开的算法,如何吃透?
  2. Java加载词向量_W2C得到词向量之后,如何得到句子向量,
  3. activity中fragment 返回键不退出_优雅地处理加载中(loading),重试(retry)和无数据(empty)等...
  4. 一句话实现php日期转中文汉字
  5. Spring| BeanCurrentlyInCreationException: Error creating bean with name ‘‘xxx“
  6. qt扫雷鼠标c语言中文网,基于C语言实现的扫雷游戏代码
  7. 令人泪目 浙江江山古稀老人照顾俩脑瘫儿近半世纪
  8. 寻找相同的乱序字符串
  9. nettry 入站事件如何传递到下一个handler
  10. 计算机网络复习-数据链路层
  11. 产品专利和方法专利对比分析
  12. 手机的1G,2G,3G和4G区别识记
  13. 考研英语作文—谋篇布局
  14. MAC直接的剪切快捷键
  15. HDU6438-Buy and Resell(贪心、思维题)
  16. 在Windows 7和Vista中禁用程序兼容性助手
  17. c语言西华大学陈晓亮,计算机与软件工程学院
  18. KindEditor实现多图片上传
  19. Modelsim仿真操作指导
  20. 如何使用TensorRT加速深度学习推理

热门文章

  1. Cesium的坐标拾取详解
  2. 人生重开模拟器 的主逻辑:每一年先判断天赋再判断事件
  3. 模电-基本放大电路-共射放大
  4. 用骈文写一段自我检讨
  5. 抖音多账号零粉直播工具源码实现无人直播
  6. java设计模式之门面模式
  7. 2021年度总结——熬了3 年的芯片今晚来了
  8. 关于、、的含义及区别
  9. 中国AI企业不惧美国封杀 百度华为用一张图给你答案!
  10. JavaScript设计模式学习(四)单件(Singleton Pattern)