Hibernate五 HQL查詢


HQL查詢
一 介紹
1.HQL:Hibernate Query Language,是一種完全面向對象的查詢語言。
使用Hibernate有多重查詢方式可供選擇:hibernate的HQL查詢,也可以使用條件查詢,甚至使用原生的SQL查詢語句。Hibernate還提供了一種數據過濾功能,這些都用於刪選目標數據。
2.查詢步驟:
(1)獲取Hibernate Session對象
(2)編寫HQL語句
(3)以HQL語句為參數,調用Session的createQuery()方法創建查詢對象
(4)如果HQL語句包含參數,則調用Query的setXxx()方法為參數賦值
(5)調用Query對象的list()或uniqueResult()方法返回查詢結果列表
例如:假設兩個關聯實體Person和MyEvent之間存在中N--N關聯關系,具體的查詢如下:
private class HqlQuery{
public static void main(String[] args) throws Exception{
HqlQuery mgr=new HqlQuery();
mgr.findPersons();
}
private void findPersons(){
Session sess=HibernateUtil.currentSession();
Transaction tx=sess.beginTransaction();
//以HQL語句創建Query對象
List p1=sess.creatQuery("select distinct p from Person p "+
"join p.myEvents where title= :eventTitle")
.setString("eventTitle","a simple title");
.list();
//遍歷查詢的全部結果
for(Object ele:p1){
Person p=(Person)ele;
System.out.println(p.getName());
}
tx.commit();
HibernateUtil.closeSession();
}
}
注意:Query對象可以連續多次為HQL參數賦值,因為setXxx()方法返回的是Query本身,最后調用list()方法返回查詢到的全部結果。Query還包含如下兩個方法:
setFirstResult(int firstResult):設置返回的結果集從第幾條記錄開始
setMaxResult(int maxResults):設置本次查詢返回的結果數目
HQL語句本身不區分大小寫,但是HQL語句中所使用的包名、類名、實例名、屬性名都區分大小寫
二 具體使用
1.from子句
from Person 或者是 from Person as p
as關鍵字是可選的,但是為了保留可讀性,建議保留。
from后還可以跟多個持久化類,此時將產生一個笛卡爾積或跨表的連接,但是這種做法並不經常使用,因為通常在做跨表的連接時,可以考慮使用隱式連接或顯式連接,而不是在from后緊跟多個表名。
2.關聯和連接
當程序需要從多個數據表中取得數據時,SQL語句會考慮使用多表連接查詢。Hibernate使用關聯映射處理底層數據表之間的連接,一旦提供了正確的關聯映射后,當程序通過Hibernate進行持久化訪問時,將可利用Hibernate的關聯來進行連接。
HQL支持兩種關聯連接(join):隱式和顯式
隱式連接不使用join關鍵字,使用英文點號.來隱式連接關聯實體,如:from Person p where p.myEvents.title>:title
顯式連接需要使用xxx join關鍵字,如:from Person p inner join p.myEvents event where event.happenDate<:endDate
主要有以下幾種連接方式:
inner join(內連接),簡寫為join
left outer join(左外連接),簡寫為left join
right outer join(右外連接),簡寫為right join
full join(全連接),並不常用
使用顯式連接時,還可以通過with關鍵字提供額外的連接條件,如:
from Person p inner join p.myEvents event with p.id>event.id where event.happenDate<:endDate
隱式連接底層將轉換成SQL99的交叉連接,顯式連接底層將轉換成SQL99的inner join,left join,right join等等。
注意:隱式連接和顯式連接查詢后返回的結果不同
在上述from Person p where p.myEvents.title>:title例子中,使用隱式連接查詢返回的結果是多個被查詢實體組成的集合,也就是Person對象組成的集合。
而rom Person p inner join p.myEvents event with p.id>event.id where event.happenDate<:endDate例子中,使用顯式連接查詢返回的結果也是集合,但是集合元素是被查詢的持久化對象、所有被關聯的持久化對象所組成的數組。該例中同時選擇了person和event表中的所有數據列,查詢得到的結果集的每條記錄既包含了Person實體的全部屬性,也包含了MyEvent實體的全部屬性。
Hibernate3.2.2以前的版本中,會對所有的關聯實體自動使用隱式連接,如:from Person p where p.myEvents.title =:eventTitle,但是在這以后,如果myEvents是一個集合,就會報錯:QueryException,要改寫為:
from Person p inner join p.myEvents e where e.title =:eventTitle
如果只想獲取Person組成的集合,應改為:select p from Person p inner join p.myEvents e where e.title =:eventTitle,但是這么做會產生多個完全相同的Person對象,因此要改為:select distinct p from Person p inner join p.myEvents e where e.title =:eventTitle
也就是說,對於Hibernate3.2.3以后的版本,如果關聯實體是單個實體或單個的組件屬性,就可以使用隱式連接;當關聯實體是集合,則必須使用xxx join來顯式連接關聯實體或組件。
3.select子句
select子句用於選擇指定的屬性或直接選擇某個實體,選擇的屬性必須是from后持久化類包含的屬性,如:
select p.name from Person as p
如果select后由多個選項,那么每個集合元素就是選擇出的多項組成的數組,如:
select p.name, p from Person as p
執行該HQL語句得到的集合元素就是類似於[String,Person]結構的數組
也可以將選擇出的屬性存入一個List對象中,如:
select new List(p.name, p.address) from Person as p
也可以將選擇出的屬性直接封裝成對象,如:
select new ClassTest(p.name,p.address) from Person as p
前提是ClassTest支持p.name,p.address的構造器
也可以給選中的表達式命名別名,如:
select p.name as personName from Person as p
這種做法與new map使用更為普遍:
select new map(p.name as personName) from Person p
執行上面的HQL語句返回的結果是集合,該Map對象以personName為key,實際的值為value。
4.多態查詢
from后面跟持久化類名,不僅會查詢出該持久化類的全部實例,還會查詢出該類的子類的全部實例,如:
from Person as p
該查詢語句不僅會查詢出Person的全部實例,還會查出其子類,如Teacher的全部實例。
5.where子句
where子句用來篩選選中的結果,縮小選擇的范圍。
select Person where name like 'tom%'
select Person as p where p.name like "tom%"
以上兩種寫法的效果是一樣的。
只要沒有集合屬性,使用隱式連接多個數據庫會相當方便,不會感受到多表連接查詢的繁瑣。
6.表達式
where子句后支持的運算符非常豐富,允許使用大部分SQL支持的表達式,包括:
數學運算符:+ - * /等
二進制比較運算符:= >= <= <> != like
邏輯運算符:and or not 等
in not in between is null is not null is emtpy is not empty等等
字符串連接符: value1 || value2 concat(value1,value2)
時間操作函數: current_date() current_time() current_timestamp() second() minute() hour() day() month() year()
EJB-QL3.0所支持的函數或操作:substring() trim() lower() upper() length()等等
where子句還支持以下的特殊關鍵字用法:
(1)HQL index()函數:作用於join的有序集合的別名
(2)HQL 函數,把集合作為參數:size(),minelement(),maxelement(),minindex(),maxindex()
(3)in和between...and的用法:select DemesticCat cat where cat.name between 'A' and 'B'
select DemesticCat cat where cat.name in ('Foo','Bar','Baz')
當然,也支持not between和not in的用法
(4)is null 和is not null用來測試空值
(5)size關鍵字用來返回一個集合的大小
from Cat cat where cat.kittens.size>0或者from Cat cat where size(cat.kittens)>0
(6)對於有序集合,還可以使用minindex(),maxindex()函數代表最小與最大的索引序數,如:
from Calendar cal where maxindex(order.items) >100
7.order by子句
查詢返回的集合可以根據類或組件屬性的任何屬性進行排序,如:
from Person as p order by p.name,p.age
可以使用asc或desc關鍵字指定升序或降序的排序規則,如:
from Person as p order by p.name asc,p.age desc
8.group by子句
返回聚集值的查詢可以對持久化類或組件屬性的屬性進行分組,分組使用group by子句,如:
select cat.color,sum(cat.weight),count(cat)
from Cat cat
group by cat.color
注意:出現在select后的屬性,要么出現在聚集函數中,要么出現在group by的屬性列表中。
having子句用於對分組進行過濾,如:
select cat from Cat cat
join cat.kittens kitten
group by cat
having avg(kitten.weight)>100
order by count(kitten) asc,sum(kitten.weight) desc
9.子查詢
如果底層數據庫支持子查詢,則可以在HQL語句中使用子查詢,如:
from Cat as fatcat
where fatcat.weight>(select avg(cat.weight) from DomesticCat cat);


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM