JPQL,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 |
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
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。
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。