hql語法

HQL查詢:
Criteria查詢對查詢條件進行了面向對象封裝,符合編程人員的思維方式,不過HQL(Hibernate Query Lanaguage)查詢提供了更加豐富的和靈活的查詢特性,因此
Hibernate將HQL查詢方式立為官方推薦的標準查詢方式,HQL查詢在涵蓋Criteria查詢的所有功能的前提下,提供了類似標準SQL語句的查詢方式,同時也提供了更
加面向對象的封裝。完整的HQL語句形勢如下:
Select/update/delete…… from …… where …… group by …… having …… order by …… asc/desc

其中的update/delete為Hibernate3中所添加的功能,可見HQL查詢非常類似于標準SQL查詢。由于HQL查詢在整個Hibernate實體操作體系中的核心地位,這一節我
將專門圍繞HQL操作的具體技術細節進行講解。


1、 實體查詢:
有關實體查詢技術
1 String hql=”from User user ”;
2 List<User> list=session.CreateQuery(hql).list();

?


上面的代碼執行結果是,查詢出User實體對象所對應的所有數據,而且將數據封裝成User實體對象,并且放入List<User>中返回。這里需要注意的是,Hibernate的實體查
詢存在著對繼承關系的判定,比如我們前面討論映射實體繼承關系中的Employee實體對象,它有兩個子類分別是HourlyEmployee,SalariedEmployee,如果有這樣的
HQL語句:“from Employee”,當執行檢索時Hibernate會檢索出所有Employee類型實體對象所對應的數據(包括它的子類HourlyEmployee,SalariedEmployee對應
的數據)。

因為HQL語句與標準SQL語句相似,所以我們也可以在HQL語句中使用where字句,并且可以在where字句中使用各種表達式,比較操作符以及使用“and”,”or”連接
不同的查詢條件的組合。看下面的一些簡單的例子:

復制代碼
1 from User user where user.age=20;
2 from User user where user.age between 20 and 30;
3 from User user where user.age in(20,30);
4 from User user where user.name is null;
5 from User user where user.name like ‘%zx%’;
6 from User user where (user.age%2)=1;
7 from User user where user.age=20 and user.name like ‘%zx%’;
復制代碼

?



2、 實體的更新和刪除:
?? 在繼續講解HQL其他更為強大的查詢功能前,我們先來講解以下利用HQL進行實體更新和刪除的技術。這項技術功能是Hibernate3的新加入的功能,在Hibernate2
中是不具備的。比如在Hibernate2中,如果我們想將數據庫中所有18歲的用戶的年齡全部改為20歲,那么我們要首先將年齡在18歲的用戶檢索出來,然后將他們的
年齡修改為20歲,最后調用Session.update()語句進行更新。在Hibernate3中對這個問題提供了更加靈活和更具效率的解決辦法,如下面的代碼:
1 Transaction trans=session.beginTransaction();
2 String hql=”update User user set user.age=20 where user.age=18”;
3 Query queryupdate=session.createQuery(hql);
4 int ret=queryupdate.executeUpdate();
5 trans.commit();

?


通過這種方式我們可以在Hibernate3中,一次性完成批量數據的更新,對性能的提高是相當的可觀。同樣也可以通過類似的方式來完成delete操作,如下面的代碼

1 Transaction trans=session.beginTransaction();
2 String hql=”delete from User user where user.age=18”;
3 Query queryupdate=session.createQuery(hql);
4 int ret=queryupdate.executeUpdate();
5 trans.commit();

?


如果你是逐個章節閱讀,那么你一定會記起我在第二部分中有關批量數據操作的相關論述中,討論過這種操作方式,這種操作方式在Hibernate3中稱為bulk
delete/update,這種方式能夠在很大程度上提高操作的靈活性和運行效率,但是采用這種方式極有可能引起緩存同步上的問題(請參考相關論述)。


3、 屬性查詢:
部分屬性檢索
很多時候我們在檢索數據時,并不需要獲得實體對象所對應的全部數據,而只需要檢索實體對象的部分屬性所對應的數據。這時候就可以利用HQL屬性查詢技術,如下面程序示例:
1 List list=session.createQuery(“select user.name from User user ”).list();
2 for(int i=0;i<list.size();i++){
3  System.out.println(list.get(i));
4 }

?


我們只檢索了User實體的name屬性對應的數據,此時返回的包含結果集的list中每個條目都是String類型的name屬性對應的數據。我們也可以一次檢索多個屬性,
如下面程序:
1 List list=session.createQuery(“select user.name,user.age from User user ”).list();
2 for(int i=0;i<list.size();i++){
3  Object[] obj=(Object[])list.get(i);
4  System.out.println(obj[0]);
5  System.out.println(obj[1]);
6 }

?


此時返回的結果集list中,所包含的每個條目都是一個Object[]類型,其中包含對應的屬性數據值。作為當今我們這一代深受面向對象思想影響的開發人員,可能
會覺得上面返回Object[]不夠符合面向對象風格,這時我們可以利用HQL提供的動態構造實例的功能對這些平面數據進行封裝,如下面的程序代碼:
復制代碼
1 List list=session.createQuery(“select new User(user.name,user.age) from User user ”).list();
2 for(int i=0;i<list.size();i++){
3  User user=(User)list.get(i);
4  System.out.println(user.getName());
5  System.out.println(user.getAge());
6 }
復制代碼

?


這里我們通過動態構造實例對象,對返回結果進行了封裝,使我們的程序更加符合面向對象風格,但是這里有一個問題必須注意,那就是這時所返回的User對象,
僅僅只是一個普通的Java對象而已,除了查詢結果值之外,其它的屬性值都為null(包括主鍵值id),也就是說不能通過Session對象對此對象執行持久化的更新操
作。如下面的代碼:
復制代碼
1 List list=session.createQuery(“select new User(user.name,user.age) from User user ”).list();
2 for(int i=0;i<list.size();i++){
3  User user=(User)list.get(i);
4  user.setName(“gam”);
5  session.saveOrUpdate(user);
6 /*這里將會實際執行一個save操作,而不會執行update操作,因這User對象的id屬性為null,Hibernate會把它作為一個自由對
7 象(請參考持久化對象狀態部分的論述),因此會對它執行save操作。*/
8 }
復制代碼

?

4、 分組與排序
A、Order by子句:
? 與SQL語句相似,HQL查詢也可以通過order by子句對查詢結果集進行排序,并且可以通過asc或者desc關鍵字指定排序方式,如下面的代碼:
1
from User user order by user.name asc,user.age desc;

  


上面HQL查詢語句,會以name屬性進行升序排序,以age屬性進行降序排序,而且與SQL語句一樣,默認的排序方式為asc,即升序排序。

B、Group by子句與統計查詢:
在HQL語句中同樣支持使用group by子句分組查詢,還支持group by子句結合聚集函數的分組統計查詢,大部分標準的SQL聚集函數都可以在HQL語句中使用,比如:
count(),sum(),max(),min(),avg()等。如下面的程序代碼:
1 String hql=”select count(user),user.age from User user group by user.age having count(user)>10 ”;
2 List list=session.createQuery(hql).list();

?


C、優化統計查詢:
假設我們現在有兩張數據庫表,分別是customer表和order表,它們的結構如下:
復制代碼
customer 
ID varchar2(14) 
age number(10) 
name varchar2(20)order 
ID varchar2(14) 
order_number number(10) 
customer_ID varchar2(14)
復制代碼

?

現在有兩條HQL查詢語句,分別如下:
from Customer c inner join c.orders o group by c.age;(1)select c.ID,c.name,c.age,o.ID,o.order_number,o.customer_ID
from Customer c inner join c.orders c group by c.age;(2)

?


這兩條語句使用了HQL語句的內連接查詢(我們將在HQL語句的連接查詢部分專門討論),現在我們可以看出這兩條查詢語句最后所返回的結果是一樣的,但是它們
其實是有明顯區別的,語句(1)檢索的結果會返回Customer與Order持久化對象,而且它們會被置于Hibernate的Session緩存之中,并且Session會負責它們在緩存
中的唯一性以及與后臺數據庫數據的同步,只有事務提交后它們才會從緩存中被清除;而語句(2)返回的是關系數據而并非是持久化對象,因此它們不會占用
Hibernate的Session緩存,只要在檢索之后應用程序不在訪問它們,它們所占用的內存就有可能被JVM的垃圾回收器回收,而且Hibernate不會同步對它們的修改。
在我們的系統開發中,尤其是Mis系統,不可避免的要進行統計查詢的開發,這類功能有兩個特點:第一數據量大;第二一般情況下都是只讀操作而不會涉及到對統
計數據進行修改,那么如果采用第一種查詢方式,必然會導致大量持久化對象位于Hibernate的Session緩存中,而且Hibernate的Session緩存還要負責它們與數據
庫數據的同步。而如果采用第二種查詢方式,顯然就會提高查詢性能,因為不需要Hibernate的Session緩存的管理開銷,而且只要應用程序不在使用這些數據,它
們所占用的內存空間就會被回收釋放。
因此在開發統計查詢系統時,盡量使用通過select語句寫出需要查詢的屬性的方式來返回關系數據,而避免使用第一種查詢方式返回持久化對象(這種方式是在有
修改需求時使用比較適合),這樣可以提高運行效率并且減少內存消耗。㊣真正的高手并不是精通一切,而是精通在合適的場合使用合適的手段


5、 參數綁定:
Hibernate中對動態查詢參數綁定提供了豐富的支持,那么什么是查詢參數動態綁定呢?其實如果我們熟悉傳統JDBC編程的話,我們就不難理解查詢參數動態綁定,
如下代碼傳統JDBC的參數綁定:
PrepareStatement pre=connection.prepare(“select * from User where user.name=?”);
pre.setString(1,”zhaoxin”);
ResultSet rs=pre.executeQuery();
在Hibernate中也提供了類似這種的查詢參數綁定功能,而且在Hibernate中對這個功能還提供了比傳統JDBC操作豐富的多的特性,在Hibernate中共存在4種參數綁
定的方式,下面我們將分別介紹:
A、按參數名稱綁定:
?在HQL語句中定義命名參數要用”:”開頭,形式如下:
?
1  Query query=session.createQuery(“from User user where user.name=:customername and user.customerage=:age ”);
2  query.setString(“customername”,name);
3  query.setInteger(“customerage”,age);

?


?上面代碼中用:customername和:customerage分別定義了命名參數customername和customerage,然后用Query接口的setXXX()方法設定名參數值,setXXX()方法包
含兩個參數,分別是命名參數名稱和命名參數實際值。
B、按參數位置邦定:
?在HQL查詢語句中用”?”來定義參數位置,形式如下:
1  Query query=session.createQuery(“from User user where user.name=? and user.age =? ”);
2  query.setString(0,name);
3  query.setInteger(1,age);

?


同樣使用setXXX()方法設定綁定參數,只不過這時setXXX()方法的第一個參數代表邦定參數在HQL語句中出現的位置編號(由0開始編號),第二個參數仍然代表參
數實際值。
注:在實際開發中,提倡使用按名稱邦定命名參數,因為這不但可以提供非常好的程序可讀性,而且也提高了程序的易維護性,因為當查詢參數的位置發生改變時
,按名稱邦定名參數的方式中是不需要調整程序代碼的。
C、setParameter()方法:
?在Hibernate的HQL查詢中可以通過setParameter()方法邦定任意類型的參數,如下代碼:
1  String hql=”from User user where user.name=:customername ”;
2  Query query=session.createQuery(hql);
3  query.setParameter(“customername”,name,Hibernate.STRING);

?


?如上面代碼所示,setParameter()方法包含三個參數,分別是命名參數名稱,命名參數實際值,以及命名參數映射類型。對于某些參數類型setParameter()方法可
以更具參數值的Java類型,猜測出對應的映射類型,因此這時不需要顯示寫出映射類型,像上面的例子,可以直接這樣寫:
query.setParameter(“customername”,name);但是對于一些類型就必須寫明映射類型,比如java.util.Date類型,因為它會對應Hibernate的多種映射類型,比如
Hibernate.DATA或者Hibernate.TIMESTAMP。
D、setProperties()方法:
在Hibernate中可以使用setProperties()方法,將命名參數與一個對象的屬性值綁定在一起,如下程序代碼:
1 Customer customer=new Customer();
2 customer.setName(“pansl”);
3 customer.setAge(80);
4 Query query=session.createQuery(“from Customer c where c.name=:name and c.age=:age ”);
5 query.setProperties(customer);

?


setProperties()方法會自動將customer對象實例的屬性值匹配到命名參數上,但是要求命名參數名稱必須要與實體對象相應的屬性同名。
這里還有一個特殊的setEntity()方法,它會把命名參數與一個持久化對象相關聯,如下面代碼所示:
1 Customer customer=(Customer)session.load(Customer.class,”1”);
2 Query query=session.createQuery(“from Order order where order.customer=:customer ”);
3 query. setProperties(“customer”,customer);
4 List list=query.list();

?


上面的代碼會生成類似如下的SQL語句:
Select * from order where customer_ID=’1’;

?


E、使用綁定參數的優勢:
我們為什么要使用綁定命名參數?任何一個事物的存在都是有其價值的,具體到綁定參數對于HQL查詢來說,主要有以下兩個主要優勢:

①可以利用數據庫實施性能優化,因為對Hibernate來說在底層使用的是PrepareStatement來完成查詢,因此對于語法相同參數不同的SQL語句,可
以充分利用預編譯SQL語句緩存,從而提升查詢效率。

②可以防止SQL Injection安全漏洞的產生:
SQL Injection是一種專門針對SQL語句拼裝的攻擊方式,比如對于我們常見的用戶登錄,在登錄界面上,用戶輸入用戶名和口令,這時登錄驗證程序可能會生成如
下的HQL語句:
“from User user where user.name=’”+name+”’ and user.password=’”+password+”’ ”
這個HQL語句從邏輯上來說是沒有任何問題的,這個登錄驗證功能在一般情況下也是會正確完成的,但是如果在登錄時在用戶名中輸入”zhaoxin or ‘x’=’x”,
這時如果使用簡單的HQL語句的字符串拼裝,就會生成如下的HQL語句:
“from User user where user.name=’zhaoxin’ or ‘x’=’x’ and user.password=’admin’ ”;
顯然這條HQL語句的where字句將會永遠為真,而使用戶口令的作用失去意義,這就是SQL Injection攻擊的基本原理。
而使用綁定參數方式,就可以妥善處理這問題,當使用綁定參數時,會得到下面的HQL語句:
from User user where user.name=’’zhaoxin’’ or ‘’x=’’x’’ ‘ and user.password=’admin’;由此可見使用綁定參數會將用戶名中輸入的單引號解
析成字符串(如果想在字符串中包含單引號,應使用重復單引號形式),所以參數綁定能夠有效防止SQL Injection安全漏洞。

轉載于:https://www.cnblogs.com/anzmri/p/8119093.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/252601.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/252601.shtml
英文地址,請注明出處:http://en.pswp.cn/news/252601.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

四五月份:關鍵詞是溝通、繪畫和SQL

例行總結一下四五月份的感受。 關鍵詞有三個&#xff1a;溝通、繪畫和SQL。 整體來說&#xff0c;這兩個月在努力跟這三個關鍵詞死磕&#xff0c;略有些進展&#xff0c;因此匯報一下。 雖然這三個關鍵詞從重要度來說是從左到右的&#xff0c;但從敘述來講&#xff0c;還是先從…

InfiniBand簡介

一&#xff0e;什么是infiniband InfiniBand架構是一種支持多并發鏈接的“轉換線纜”技術&#xff0c;它是新一代服務器硬件平臺的I/O標準。由于它具有高帶寬、低延時、 高可擴展性的特點&#xff0c;它非常適用于服務器與服務器&#xff08;比如復制&#xff0c;分布式工作等…

程序員的視角:java GC

GC&#xff08;Garbage Collection 垃圾回收&#xff09;的概念隨著 java 的流行而被人們所熟知。 實際 GC 最早起源于20世紀60年代的 LISP 語言&#xff0c;是一種自動的內存管理機制。 GC 要解決的問題有 3 個&#xff1a;1. 回收什么&#xff1f;&#xff08;what&#xff0…

spring mvc攔截器HandlerInterceptor

本文主要介紹springmvc中的攔截器&#xff0c;包括攔截器定義和的配置&#xff0c;然后演示了一個鏈式攔截的測試示例&#xff0c;最后通過一個登錄認證的例子展示了攔截器的應用 攔截定義 定義攔截器&#xff0c;實現HandlerInterceptor接口。接口中提供三個方法。 public cla…

mysql show 語句大全

mysql show 語句大全 show open tables; 基于本人對MySQL的使用&#xff0c;現將常用的MySQL show 語句列舉如下&#xff1a; 1.show databases ; // 顯示mysql中所有數據庫的名稱 2.show tables [from database_name]; // 顯示當前數據庫中所有表的名稱 3.show columns from …

阿里云Aliplayer高級功能介紹(一):視頻截圖

基本介紹H5 Video是不提供截圖的API的&#xff0c; 視頻截圖需要借助Canvas&#xff0c;通過Canvas提供的drawImage方法&#xff0c;把Video的當前畫面渲染到畫布上&#xff0c; 最終通過toDataURL方法可以導出圖片的base64編碼&#xff0c;基本就完成了圖片截圖的功能。 功能實…

POJ 1151 Atlantis 線段樹+掃描線

解題思路: 先將y軸進行離散化。n個矩形的2n個橫邊縱坐標共構成最多2n-1個區間的邊界&#xff0c;對這些區間編號&#xff0c;建立起線段樹。 x軸記錄左邊和右邊&#xff0c;左邊時是矩形面積增加&#xff0c;覆蓋層數增加邊&#xff0c;右邊是形面積減少&#xff0c;覆蓋層數減…

分頁

1.首先在數據庫中建立一個視圖&#xff08;在aspx中sql查詢語句是view_student不是student&#xff09;&#xff0c;在視圖里創建create view view_student--創建視圖as row_number 行號 一條數據是一行 分頁功能要根據行數運算select *,row_number() over(order by stuNo desc…

NFS服務端的安裝

執行以下四步操作即可完成在虛擬機上安裝完成NFS的服務端&#xff1a;第一步&#xff1a;在虛擬機上安裝nfs服務&#xff1a; sudo apt install nfs-kernel-server 第二步&#xff1a;修改文件 sudo vi /etc/exports 在文件末尾增加 /home/zzf/hisi-sdk 192.16…

【C++STL/紅黑樹】POJ 3481 DoubleQueue

POJ 3481 Double Queue 描述&#xff1a; 新成立的BIG-Bank在不切雷斯特開了一間新辦公室,使用了由IBM羅馬尼亞的現代計算機辦公環境,運用了現代信息技術.一般來說,銀行的每個顧客都有一個識別碼K,并且每一個來銀行的顧客都會被給予一個優先級P.銀行主管的一個大膽想法震驚了公…

基礎表單筆記

表單數據要向服務端提交的話 每個表單都要指定一些屬性就是name""和value"" value就是用戶寫什么就是什么 來提交name就是對這個表單進行一個標識 <from> 輸入用戶名<input type"text" name"user" value""/>這…

PCIE總線-PCI、PCIE關系及信號定義

PCI(Peripheral Component Interconnect)總線規范在上世紀九十年代由Intel提出。在處理器體系結構中&#xff0c;PCI總線屬于局部總線(Local Bus)。局部總線作為系統總線的延伸&#xff0c;主要功能是為了連接外部設備。 處理器主頻的不斷提升&#xff0c;要求速度更快&#x…

SQL Server:SQL Like 通配符特殊用法:Escape

%&#xff1a;匹配零個及多個任意字符&#xff1b; _&#xff1a;與任意單字符匹配&#xff1b; []&#xff1a;匹配一個范圍&#xff1b; [^]&#xff1a;排除一個范圍 &#xff1b;-&#xff1a;連字符 Symbol Meaning like 5[%] 5% like [_]n _n like [a-cdf] a, b, c, d, o…

案例篇-HBase RowKey 設計指南

1.為什么 Rowkey 這么重要 1.1 RowKey 到底是什么 我們常說看一張 HBase 表設計的好不好&#xff0c;就看它的 RowKey 設計的好不好。可見 RowKey 在 HBase 中的地位。那么 RowKey 到底是什么?RowKey 的特點 如下: 類似于 MySQL、Oracle 中的主鍵&#xff0c;用于標示唯一的行…

PCIe簡介及引腳定義

隨著現代處理器技術的發展&#xff0c;在互連領域中&#xff0c;使用高速差分總線替代并行總線是大勢所趨。與單端并行信號相比&#xff0c;高速差分信號可以使用更高的時鐘頻率&#xff0c;從而使用更少的信號線&#xff0c;完成之前需要許多單端并行數據信號才能達到的總線帶…

IDEA下搜狗輸入法輸入中文時卡著不動的參考解決方法

【問題描述】 在IntelliJ IDEA工具的java編輯窗口&#xff0c;給代碼增加注釋時發現&#xff0c;輸入中文時&#xff0c;搜狗輸入法界面不動&#xff0c;只顯示第一個字母。如圖&#xff1a; 我想輸入“根據”兩個字&#xff0c;但搜狗輸入法界面一直卡著不刷新&#xff0c;導…

6U VPX板卡資料:6U VPX 高性能計算存儲板卡

6U VPX板卡資料&#xff1a;6U VPX 高性能計算存儲板卡_hexiaoyan827的博客-CSDN博客_vpx板卡

Android: Custom View和include標簽的區別

Custom View&#xff0c; 使用的時候是這樣的&#xff1a; <com.example.home.alltest.view.MyCustomViewandroid:id"id/customView"android:layout_width"match_parent"android:layout_height"wrap_content"></com.example.home.allte…

七 web爬蟲講解2—urllib庫爬蟲—狀態嗎—異常處理—瀏覽器偽裝技術、設置用戶代理...

如果爬蟲沒有異常處理&#xff0c;那么爬行中一旦出現錯誤&#xff0c;程序將崩潰停止工作&#xff0c;有異常處理即使出現錯誤也能繼續執行下去 1.常見狀態嗎 301&#xff1a;重定向到新的URL&#xff0c;永久性302&#xff1a;重定向到臨時URL&#xff0c;非永久性304&#x…