JPQL


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

1、查询实体

SELECT c FROM Customer c

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

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

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

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

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

2、实体属性

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

SELECT c.name FROM Customer c

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

SELECT c.address FROM Customer c

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

 

3、关联查询

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

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

tb_customer数据

id

name

email

address_id

1

zhangsan

zhangsan@163.com

6

2

lisi

lisi@163.com

7

3

wangwu

wangwu@163.com

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

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、BETWEEN

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

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

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

6、IN

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

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

7、LIKE

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

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

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

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

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

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

 

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

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

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个以上的订单

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

 

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

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值