JPQL

5、       JPQL

JPQL(JavaPersistence Query Language),是基于实体的查询,所查询的内容都是实体或实体属性。

5.1、查询实体

SELECT c FROM Customer c

JPQL语句与SQL基本类似,但它是基于实体的查询。在初次使用时,需要注意以下几个问题。

1)     实体名和属性区分大小写;

2)     JPQL中的保留关键字不区分大小写;

3)     标识实体的别名,也不区分大小写;

4)     实体的别名可以使用AS关键字来标识,AS关键字也可以省略;

5.2、实体属性

查询时如果使用了实体的别名,在SELECT查询时便可以引用该实体的属性(而不是表的字段名),如下:

SELECT c.name FROM Customer c

如果查询的实体属性是另一个实体(一对一关系),也可以通过属性后“.”来获得实体的属性,如下

SELECT c.address FROM Customer c

SELECT c.address.street FROM Customer c(多级导航)

5.3、关联查询

JPA提供了两种显示关联实体的方式,分别为内连接(INNERJOIN)和左外连接(LEFTOUTER JOIN)。

首先回顾下传统SQL中的内连接、外连接、左连接、右连接方式。假设有表tb_customer和表tb_order分别对应实体Customer和Order,表中数据如下

tb_customer数据


id


name


email


address_id


1


zhangsan


[email protected]


6


2


lisi


[email protected]


7


3


wangwu


[email protected]


8

tb_order数据


id


num


customer_id


create_date


5


10002


1


6


10003


1


7


10004


5


8


10005


1


9


10006


3

1)     内连接

内连接查询也叫自然连接查询,它是两个表关联的最小集合。也就是说,左表中的数据和右表中的数据都存在时才会关联,并且执行内连接查询时不会出现null值。如执行下面的SQL语句

SELECT * from tb_customer c INNER JOIN tb_order o ONc.id=o.customer_id

查询的结果如下


c.id


c.name


o.id


o.num


o.customer_id


1


zhangsan


5


10002


1


1


zhangsan


6


10003


1


1


zhangsan


8


10005


1


3


wangwu


9


10006


3

左表为tb_customer,右表为tb_oreder。左表中id=2的记录,在右表中不存在。右表中id=7的记录,在左表中也不存在,所以在使用内连接查询时不存在着两项数据。

2)     左连接

左连接是以左表为基础,如果右表的数据有关联则显示,如果右表中没有数据则显示为null。也就是说左连接查询的全部是坐标的数据,而右表的数据不一定是全部的,如下

SELECT * from tb_customer c LEFT JOIN tb_order o ONc.id=o.customer_id


c.id


c.name


o.id


o.num


o.customer_id


1


zhangsan


5


10002


1


1


zhangsan


6


10003


1


1


zhangsan


8


10005


1


2


lisi


null


null


null


3


wangwu


9


10006


3

3)     右连接查询

右连接查询与左连接查询相反,它是以右表为查询基础。如果左表数据有关联则显示,没有则显示null。如下

SELECT * from tb_customer c RIGHT JOIN tb_order o ONc.id=o.customer_id


c.id


c.name


o.id


o.num


o.customer_id


1


zhangsan


5


10002


1


1


zhangsan


6


10003


1


null


null


7


10004


5


1


zhangsan


8


10005


1


3


wangwu


9


10006


3

4)     外连接查询

外连接查询是相对于内连接查询来说的,总的来说左连接查询和右连接查询都属于外连接查询,只不过是方向不同而已。

表连接查询的关系如下图所示:

与传统的SQL语句相比,JPA只提供了两种方式的表连接:内连接和左连接。

l  内连接

内连接是最常用的连接方式,连接后关联数据不会出现null值,语法如下:

[INNER] JOIN

SELECT c,o FROM Customer c JOIN c.orders o

l  左连接

左连接也可以叫做左外连接,它是以左表为基础,关联右表。连接后右表中的数据可能为null值,如下

LEFT[OUTER] JOIN

SELECT  c,o FROMCustomer c LEFT JOIN c.orders o

此时,查询结果是所有的客户,即使客户没有订单,也是可以查询到的。

l  抓取连接

实体属性的加载有两种方式,分为即时加载和懒加载。同样,对于实体关联的查询,也可以设置查询时的加载方式,这就是抓取连接,如下

[LEFT|INNER] JOIN FETCH

简单地说在JOIN关键字后加上FETCH关键字,则表示查询为抓取查询。事实上抓取连接主要针对实体属性为懒加载方式的,使用内连接并没有加载关联的实体,如下

SELECT c FROM Customer c JOIN c.orders o

此时在客户端调用getOrders方法将抛出异常。但若将关联查询设置为抓取方式,如下

SELECT c FROM Customer c JOIN FETCH

则查询结果的customer对性已加载所关联的orders属性。

l  唯一性

当进行连接查询时,通常会产生一些重复数据,若要去掉重复的数据,在关联查询时可以使用DISTINCT关键字,如下

SELECT DISTINCT c FROM Customer c JOIN c.orders o

5.4、操作符

WHERE条件表达式可以包含比较操作符和逻辑操作符,如下

l  比较操作符

=、>、>=、<、<=、<>、[NOT]BETWEEN、[NOT]LIKE、

[NOT] BETWEEN、[NOT] IN、IS [NOT] NULL、IS [NOT]EMPTY、[NOT]MEMBER OF

l  逻辑操作符

NOT、AND、OR

5.5、BETWEEN

BETWEEN 操作符是查询值在某一个指定范围内的缩写,语法如下:

[NOT] BETWEEN 范围值一 AND 范围值二

SELECT c FROM Customer WHRER c.asset BETWEEN 1000.0 and2000.0

5.6、IN

IN操作符可以查询在指定的多个值,语法如下:

[NOT] IN (值{,值}*|子查询)

5.7、LIKE

LIKE 操作符用来查询匹配指定的字符串,匹配字符串的关键字符有以下两种:

1)         下画线“_”:表示匹配某一个字符;

2)         百分号:表示匹配零个或多个字符;

如果要查询的字符串存在“_”或“%”,则需要在匹配的字符串前转移字符“\”。

5.8、NULL

NULL操作符用来判断属性是否是null值,如下

判断属性是null,使用“ISNULL”关键字,如下

SELECT c FROM Customer c WHERE c.address IS NULL

判断属性不为null,使用“IS NOTNULL”关键字,如下

SELECT c FROM Customer c WHERE c.address IS NULL

NULL操作符也可以用在参数查询中,用于判断输入的参数是否为null值,如下

SELECT c FROM Customer c WHERE :zip IS NOT NULLL ANDc.address.zip=:zip

5.9、EMPTY

EMPTY操作符用于判断实体的集合类属性是否为空。它与NULL操作符不太相同,主要是针对属性是集合类的判断。

判断集合类属性为空值,使用IS EMPTY,如下

SELECT c FROM Customer c WHERE c.orders IS EMPTY

注意:当使用内连接查询时,由于此时关联后的表中没有null值,所以即使查询到空值,查询结果中也不会出现,所以在使用内连接查询时注意不要使用IS
MPTY来判断空值,如下

SELECT c FROM Customer c JOIN c.orders o WHERE c.orders ISEMPTY

判断集合类属性不是空值,使用IS NOT EMPTY,如下

SELECT c FROM Customer c WHERE c.orders IS NOT EMPTY

5.10、MEMBER OF

MEMBER OF操作符用于判断一个实体是否包含在集合类对象中(MEMBEROF 前可以添加NOT),如下

//查询订单号为1的客户实体

SELECT c FROM Customer c WHERE :order MEMBER OF c.orders

Query query=entityManager.createQuery(jpql);

Order o=entityManager.find(Order.class,1);

query.setParameter(“order”,o);

5.11、函数表达式

JPQL中也定义了一些常用的函数,这些函数可以针对字符型、数值型和日期型数值使用。

字符串函数

字符串函数通常可在查询时使用,例如查询顾客姓名的长度大于10的JPQL语句如下:

SELECT c FROM Customer c WHERE LENGTH(c.name)>10

JPQL 中提供的字符串函数主要有:

3)   CONCAT(str1,str2):返回连接两个字符串的值

4)   SUBSTRING(str,start,len):返回字符串的一段,start为字符串的开始索引位(第一个字符位置为1),len为截取的长度;

5)   TRIM(str):去掉字符串的首尾的空格;

6)   LENGTH(str):返回字符串的长度;

数值函数

数值函数通常也可以在查询时使用,如下:

SELECT c FROM Customer c WHERE ABS(c.asset)>20

JPQL 中提供的主要数值函数有:

l  ABS(num):返回数的绝对值;

l  SQRT(num):返回数的平方;

l  MOD(int,int):取模;

l  SIZE:返回集合类的总数;

日期函数

JPA提供了三种获取系统当前时间的格式的方法:

l  CURRENT_DATE

l  CURRENT_TIME

l  CURRENT_TIMESTAMP

5.12、子查询

当一个查询条件依赖于另一个查询结果时,就需要使用子查询(嵌套查询),如下

SELECT c FROM Customer c WHERE c.age > (SELECT AVG(c.age)FROM Customer c)

EXISTS表达式

EXISTS表达式用于判断子查询的结果,如果子查询的结果有一个或多个,则返回true;如果子查询没有返回任何结果,则返回false。语法如下:

[NOT] EXISTS (子查询表达式)

如查询系统当前日期之前的订单所属的客户,如下

SELECT c FROM Customer c WHERE EXISTS

(SELECT o FROM c.orders o WHERE o.createTime <CURRENT_DATE)

也可以在EXISTS关键字前加上“NOT”表示不存在,查询结果正好与EXISTS相反。

ALL和ANY表达式

当子查询的返回结果有多个,顶层查询的条件使用=,<,<=,>,>=,<>这些比较来满足条件,就需要使用ALL、ANY和SOME(ANY、SOME与NOT ALL等价,只要存在一个即可)表达式,基本语句入如下:

{ALL|ANY|SOME}(子查询)

SELECT o FROM Order o WHERE 50 < ANY (SELECT l.quantityFROM o.lineItems l)  //查询订单明细中存在50个以上的订单

5.13、分组

分组查询是JPQL中很重要的查询,它可以按照指定的属性将数据分组,通常在统计数据时使用。

分组查询通常使用“GROUPBY”表达式和“HAVING”表达式,分组查询的基本语法如下:

GROUP BY <分组子句>(HAVING<having 子句>)

“GROUPBY”关键字后指明分组的属性,“HAVING”则可以对分组后的数据进行过滤,作用相当于WHERE子句,只能用在分组查询中,如下

SELECT c FROM Customer c GROUP BY c.asset HAVING AVG(c.asset)>1000

5.14、排序

ORDER BY子句可以对查询结果进行排序,语法如下:

ORDER BY 排序属性[ASC |DESC]{, 排序属性[ASC |DESC]}*

其中“ORDERBY”关键字后指定排序的属性,多个属性排序用分号分割,如下:

SELECT c FROM Customer c ORDER BY c.id ASC,c.name DESC

注意:在动态组装JPQL指定多个排序域时,不能使用HashMap,而要使用LinkedHashMap。

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-30 18:19:31

JPQL的相关文章

JavaEE(15) - JPA查询API和JPQL

1. JPQL面向对象特征 2. 执行JPQL查询的常用API 3. 使用JPQL创建查询 4. 为JPQL设置参数 5. 获取查询结果 6. JPQL函数和JPQL表达式 7. JPQL的关联查询和多态查询 8. 对查询结果集进行分页 9. 使用JPQL子查询和命名查询 10. JPQL的批量更新和删除

JPA学习(6)JPQL

JPQL语言,即 Java Persistence Query Language 的简称.JPQL 是一种和 SQL 非常类似的中间性和对象化查询语言,它最终会被编译成针对不同底层数据库的 SQL 查询,从而屏蔽不同数据库的差异. JPQL语言的语句可以是 select 语句.update 语句或delete语句,它们都通过 Query 接口封装执行. 1.Query接口封装了执行数据库查询的相关方法.调用 EntityManager 的 createQuery.create NamedQuer

Atitit oodbms的查询,面向对象的sql查询jpa jpql hql

1.1. 标准API历史1 1.2. JPA定义了独特的JPQL(Java Persistence Query Language) 可媲美JDBC的查询能力  1 1.3. 操作api1 1.4. Hql2 1.1. 标准API历史 该标准被纳入因此标准的每一步中JPA的规范通知所有版本JPA. 在JPA2.0中,标准查询API,查询的标准化开发. 在JPA2.1,标准更新和删除(批量更新和删除)都包括在内 1.2. JPA定义了独特的JPQL(Java Persistence Query La

JPQL设置自增长、只读、文本类型等的注解

JAVA中使用JPQL 一种设置id自动生成,自增长的方法 private long id; @Id @GeneratedValue(generator="_native") @GenericGenerator(name="_native",strategy="native") public long getId() { return id; } 也有一种这样的 @Id @GeneratedValue(strategy = GenerationT

JPQL模糊匹配单个字符

JPQL模糊匹配,不是%,而是单个字符,该怎么办?比如我要查出数据库中满足后三位是数字的字符串 对于mysql来说,使用通配符 %和_可以轻松解决,但是对于JPQL来说模糊查询就伤脑筋了... 有一个方法,可以使用like查询出来以后,再在java代码里进行过滤.虽然很笨,但也有效

JPA学习笔记-JPQL

JPQL语言,即 JavaPersistence Query Language 的简称.JPQL 是一种和 SQL 非常类似的中间性和对象化查询语言,它最终会被编译成针对不同底层数据库的 SQL 查询,从而屏蔽不同数据库的差异.JPQL语言的语句可以是 select 语句.update 语句或delete语句,它们都通过 Query接口封装执行 javax.persistence.Query Query接口封装了执行数据库查询的相关方法.调用 EntityManager的 createQuery

JPA学习笔记(12)——JPQL

Query接口 int executeUpdate() 用于执行update或delete语句. List getResultList() 用于执行select语句并返回结果集实体列表. Object getSingleResult() 3用于执行只返回单个结果实体的select语句. Query setFirstResult(int startPosition) 用于设置从哪个实体记录开始返回查询结果. Query setMaxResults(int maxResult) 用于设置返回结果实体

JavaEE(14) - JPA查询API和JPQL

1. JPQL面向对象特征 2. 执行JPQL查询的常用API 3. 使用JPQL创建查询 4. 为JPQL设置参数 5. 获取查询结果 6. JPQL函数和JPQL表达式 7. JPQL的关联查询和多态查询 8. 对查询结果集进行分页 9. 使用JPQL子查询和命名查询 10. JPQL的批量更新和删除

JPA学习---第八节:使用JPQL语句进行查询

1.JPQL 语句查询,代码如下: @Test public void query(){ EntityManagerFactory factory = Persistence.createEntityManagerFactory("learn_jpa"); EntityManager em = factory.createEntityManager(); // 命名参数查询或位参数查询 Query query = em.createQuery("select p from P