hibernate -- HQL語句總結


本章介紹了Hibernate的幾種主要檢索方式:HQL檢索方式、QBC檢索方式、SQL檢索方式。HQLHibernate Query Language的縮寫,是官方推薦的查詢語言。QBCQuery By Criteria的縮寫,是Hibernate提供的一個查詢接口。Hibernate是一個輕量級的框架,它允許使用原始SQL語句查詢數據庫。

1.1 HQL基礎

HQLHiberante官方推薦的Hibernate檢索方式,它使用類似SQL的查詢語言,以面向對象的方式從數據庫中查詢。可以使用HQL查詢具有繼承、多態和關聯關系的數據。在檢索數據時應優先考慮使用HQL方式。

1.1.1 默認數據庫表和數據

在講解本章時,在沒有特殊說明時,用到的數據庫均為joblog,也就是在第4章建立的數據庫。joblog中添加了3個表:學生表student、課程表course和選課表sc

學生表student中各字段的結構如圖6-1所示,字段的中文含義在Comment列中。

Hibernate <wbr>中HQL語句(一)

6-1 學生表的數據結構

學生表student中的數據如圖6-2所示,沒有特殊說明時,用到的均為這6條記錄。

此處仍然使用在第4章建立的HibernateProject項目,但是這里新建了一個包hibernate.ch06,這個包存放本章中的所有代碼。在hibernate.ch06包中建立學生表對應的持久化類Student.java,代碼如下。

Hibernate <wbr>中HQL語句(一)

6-2 學生表中的數據

package hibernate.ch06;

 

// 學生類

public class Student {

 

    private Integer id; // 對象標識符

    private Integer sno;// 學號

    private String sname; // 姓名

    private String ssex;// 性別

    private String sdept; // 所在系別

    private Integer sage; // 年齡

    private String saddress; // 籍貫

    …… //省略了所有的get/set訪問器

 

}

課程表course中的各個字段的結構如圖6-3所示,字段的中文含義在Comment列中。

Hibernate <wbr>中HQL語句(一)

6-3 課程表的結構

課程表中的數據如圖6-4所示,如果沒有特殊說明,用到的均為這4條記錄。

Hibernate <wbr>中HQL語句(一)

6-4 課程表的數據

hibernate.ch06中新建持久化類Course.java類,代碼如下。

package hibernate.ch06;

 

// 課程類

public class Course {

 

    private Integer id; // 對象標識符

    private Integer cno;// 課程號

    private String cname; // 課程名

    private Integer Ccredit; // 學分

    …… //省略了get/set訪問器

}

選修表scscstudent-course的縮寫)的結構如圖6-5所示,字段的中文含義在Comment列中。

Hibernate <wbr>中HQL語句(一)

6-5 選修表的結構

選修表中的數據如圖6-6所示,沒有特殊說明時,用到的均為這5條記錄。

Hibernate <wbr>中HQL語句(一)

6-6 選修表的數據

hibernate.ch06中新建持久化類SC.javaSC.java的代碼如下。

package hibernate.ch06;

// 選課類

public class SC implements java.io.Serializable {

 

    private Integer id; // id

    private Integer sno; // 學號

    private Integer cno; // 課程號

    private Integer grade; // 成績

 

    public SC() {

 

    }

    …… // 省略get/set訪問器

}

后面的章節中將用這3個表和3個持久化類進行講解。

1.1.2 檢索類的所有對象

使用HQL語句可以檢索出一個類的所有對象,如HQL語句“from Student”表示檢索Student類的所有對象。下面的程序檢索學生類的所有對象。

    Query query = session.createQuery("from Student"); // 創建Query對象

    List list = query.list(); // 執行查詢

    

    // 以下代碼做顯示用,以后不再寫出來

    Iterator it = list.iterator();

    while (it.hasNext()) {

        Student stu = (Student) it.next();

        System.out.println("id" + stu.getId());

        System.out.println("name" + stu.getSname());

        System.out.println("\n");

}

Hibernate <wbr>中HQL語句(一)     session.createQuery()HQL查詢語句為參數,生成一個查詢對象。本例中的HQL語句為“from Student”,這是from子句,格式如下。

from 類名

其中,類名可以為類的全限定名,如:

from hibernate.ch06.Student

Hibernate使用自動引入功能(auto import),會自動尋找需要的類,所以不推薦使用類的全限定名。注意,類名區分大小寫,如果寫成from student,將會拋出以下異常。

java.lang.NoClassDefFoundError: hibernate/ch06/student (wrong name: hibernate/ch06/Student)

Hibernate <wbr>中HQL語句(一)     HQL關鍵字不區分大小寫,FROMfromFrom是一樣的

調用query.list()時,真正開始執行HQL查詢語句,並把查詢的結果放在List中。

本例中查詢的是Student類中的所有屬性,如果查詢Student類中的某一個或某幾個屬性,如查詢所有學生的姓名和所在系,需要用到屬性查詢。

1.1.3 檢索類的某幾個屬性

SQL語句類似,HQL語句可以檢索類的某一個或者某幾個屬性。以下代碼查詢所有學生的姓名和所在系。

    // 創建Query對象

    Query query = session.createQuery("select Student.sname,Student.sdept from Student");

    List list = query.list(); // 執行查詢

    // 以下代碼顯示查詢的信息

    Iterator it = list.iterator();

    while (it.hasNext()) {

        Object[] stu = (Object[]) it.next();

        System.out.println("id" + stu[0]);

        System.out.println("name" + stu[1]);

        System.out.println("\n");

}

Hibernate <wbr>中HQL語句(一)     屬性查詢使用select關鍵字,屬性查詢的格式如下。

select 屬性1,屬性2,… from 類名

Hibernate <wbr>中HQL語句(一)     屬性前可以加上類名加以限定,如:

select 屬性1,屬性2,… from 類名

但一般沒有必要。

屬性查詢區分大小寫,上面的代碼中如果寫成:

select SNAME,Sdept from Student

將拋出異常,提示找不到屬性SNAME和屬性Sdept

Hibernate <wbr>中HQL語句(一)     查詢結果將只顯示查詢的屬性列。

Hibernate <wbr>中HQL語句(一)     屬性查詢的結果,對於用it.next()獲得的每條記錄,可以存儲在Object[]數組中,以便進行存取。

1.1.4 指定別名

在查詢時,可以用關鍵字as指定查詢的別名,指定別名可以簡化查詢,有時必需指定別名才能進行查詢。以下代碼查詢學號中含有4的學生的姓名和所在系。

select s.sname,s.sdept from Student as s where s.sno like '%4%'from Student s

s就是類Student的別名。注意as可以省略,即下面的查詢語句和上面的語句是等效的。

select s.sname,s.sdept from Student s where s.sno like '%4%'from Student s

1.1.5 where條件子句

where條件子句跟SQL中的where條件子句類似,它檢索符合條件的對象。例如,查詢所有所在系別為計算機系的學生:

select s.sname,s.sdept from Student s where s.dept=’計算機

Hibernate <wbr>中HQL語句(一)     where子句指定查詢的條件,其語法和SQL類似。

Hibernate <wbr>中HQL語句(一)     在where子句中可以指定比較運算符:>>=<<=<>,其含義分別為大於、大於等於、小於、小於等於、不等於

查詢年齡在2223歲的學生:

from Student s where s.sage>=22 and s.sage<=23

Hibernate <wbr>中HQL語句(一)     where子句中指定查詢的屬性是否為nullis nullis not null,其含義分別表示為空和不為空。

查詢所在籍貫為空的學生:

from Student s where s.saddress is null

1.1.6 使用distinct過濾掉重復值

使用distinct關鍵字將去掉結果中的重復值,只檢索符合條件的對象。如下面的例子檢索學生實例中的不重復的年齡。

        Session session=Hsf.currentSession();//創建Session

        String hql="select distinct s.sage from Student s";       //HQL查詢語句

        Query query=session.createQuery(hql);//創建查詢

        List list=query.list();    //執行查詢

檢索的結果如下,可見結果中去掉了一個重復的22歲。

20

21

22

23

24

1.1.7 刪除對象

HQL語句可以直接對復合條件的對象進行刪除,可以指定刪除的對象,並在提交后永久持久化到數據庫。HQL使用delete進行刪除,如刪除年齡大於25歲的學生可以使用如下代碼。

        Session session=Hsf.currentSession();        //創建Session

        Transaction tx=null;       //聲明事務

        

        try{

   tx=session.beginTransaction();  //開始事務

           

  //創建查詢

   String hql="delete Student s where s.sage>25";

   Query query=session.createQuery(hql);

   query.executeUpdate();           //執行

 tx.commit();           //成功,則提交

   tx=null;

        }catch(Exception e){

   e.printStackTrace();

   if(tx!=null){

  tx.rollback();    //失敗則回滾

       

    }

        }finally{

   session.close();

        }

注意以下兩點。

Hibernate <wbr>中HQL語句(一)     在刪除對象時,執行query.executeUpdate()進行數據刪除,但只有執行了tx.commit()進行事務提交時,才真正從數據庫中刪除數據。

Hibernate <wbr>中HQL語句(一)     如果設置了級聯刪除,則與之相關聯的對象實例也被刪除。

1.1.8 更新對象值

更新對象的HQL語句與SQL語法很相似,使用update更新對象的值。如下面例子更新對象的sage屬性。

        ransaction tx=null;         //聲明事務

        try{

   tx=session.beginTransaction();  //開始事務

           

   String hql="update Student s set s.sage='22' where s.id=11";   //更新語句

   Query query=session.createQuery(hql);

   query.executeUpdate();           //執行

   tx.commit();           //成功,則提交

   tx=null;

        }catch(Exception e){

   e.printStackTrace();

   if(tx!=null){

           tx.rollback(); //失敗則回滾

   }

        }finally{

   session.close();

        }

1.1.9 查詢計算屬性值

HQL可以查詢經過計算的值,在一些需要計算的地方可以進行計算,例如查詢全體學生的姓名和出生年份。

select s.sname,2006-s.sage from Student as s

Hibernate <wbr>中HQL語句(一)     select子句十分靈活,幾乎和SQL語句有着同樣的能力,對象的屬性值可以參與運算。

Hibernate <wbr>中HQL語句(一)     這行代碼假設當前的年份是2006年。

下面是另外幾個查詢計算屬性值的例子。

select s.sname,2006-s.sage from Student as s

1.1.10 使用函數

當需要調用函數時,HQL提供了一些類似SQL的函數。這些函數可以簡化操作。例如查詢學生的姓名、出生日期和性別,其中性別用小寫表示。

select s.sname,2006-s.sage,lower(s.ssex) from Student as sselect s.sname,2006-s. sage from Student as s

1.1.11 between...and...not between... and...確定查詢范圍

between...and...用來查詢屬性值在指定范圍內的實體對象,not between...and...用來查詢屬性值不在指定范圍內的實體對象。如查詢學生年齡在2223之間的學生:

select s.sno,s.sname,s.sage from Student s where s.sage between 22 and 23

查詢將返回如下結果。

---------------------------------------------------------------------

1    20040001 李曉梅    22    計算機系   

---------------------------------------------------------------------

2    20040002 王蒙       23    外語系   

---------------------------------------------------------------------

4    20050004 李文       22    計算機系   

between后跟的是查詢范圍的下限,and后跟的是查詢范圍的上限,所以下面的查詢語句總沒有對象返回。

from Student s where s.sage between 23 and 22

1.1.12 innot in確定查詢集合

關鍵字in用來查詢指定屬性值屬於指定集合的對象,關鍵字not in用來查詢指定屬性值不屬於指定集合的對象。如查詢不是計算機系,也不是數學系的學生。

select s.sno,s.sname,s.sdept from Student s where s.sdept not in ('計算機系','數學系')

查詢將返回如下結果。

---------------------------------------------------------------------

20040002         王蒙         外語系   

---------------------------------------------------------------------

20050003         姜浩         化學系   

---------------------------------------------------------------------

20050005         薛鵬         生物系   

1.1.13 like進行模糊查詢

like進行模糊查詢時有兩個可用的通配符:“%”“_”“%”代表長度大於等於0的字符,“_”代表長度為1的單個字符

查詢姓李的學生:

select s.sno,s.sname,s.sdept from Student s where s.sname like '%%'

查詢結果如下。

---------------------------------------------------------------------

20040001         李曉梅    計算機系   

---------------------------------------------------------------------

20050004         李文       計算機系   

---------------------------------------------------------------------

20050006         李思       數學系   

查詢姓名為兩個字符的學生:

select s.sno,s.sname,s.sdept from Student s where s.sname like '__'

查詢結果如下。

---------------------------------------------------------------------

20040002    王蒙    外語系   

---------------------------------------------------------------------

20050003    姜浩    化學系   

---------------------------------------------------------------------

20050004    李文    計算機系   

---------------------------------------------------------------------

20050005    薛鵬    生物系   

---------------------------------------------------------------------

20050006    李思    數學系   

1.1.14 and邏輯與

當要檢索指定的多個條件,且條件的邏輯關系為與時,使用“and”關鍵字。如檢索計算機系的女生,這個檢索要求包含兩個條件:計算機系女生

select s.sno,s.sname,s.sdept from Student s where s.sdept='計算機系' and s.ssex='F'

檢索的結果如下。

---------------------------------------------------------------------

20040001         李曉梅    計算機系   

---------------------------------------------------------------------

20050004         李文      計算機系   

1.1.15 or邏輯或

當檢索的多個條件,且條件的邏輯關系為或時,使用“or”關鍵字。如檢索姓王,或者年齡大於22歲的學生:

select s.sno,s.sname,s.sdept from Student s where s.sname like '%' or s.sage>22

檢索結果如下。

---------------------------------------------------------------------

20040002         王蒙         外語系   

---------------------------------------------------------------------

20050005         薛鵬         生物系

1.1.16 order by對結果進行排序

“order by”關鍵字對結果進行排序,默認為升序。“order by asc”為升序,“order by desc”為降序。例如將學生表中的學生按照年齡升序排序:

from Student s order by s.sage

檢索結果如下。

---------------------------------------------------------------------

6    20050006         李思         20         數學系   

---------------------------------------------------------------------

3    20050003         姜浩         21         化學系   

---------------------------------------------------------------------

1    20040001         李曉梅      22        計算機系   

---------------------------------------------------------------------

4    20050004         李文         22         計算機系   

---------------------------------------------------------------------

2    20040002         王蒙         23         外語系   

---------------------------------------------------------------------

5    20050005         薛鵬         24         生物系   

將學生表中的學生按照年齡降序排列,按照所在系升序排列。

from Student s order by s.sage,s.sdept desc

1.1.17 group by對記錄進行分組

對查詢進行分組可以對查詢進行細化。分組經常和聚集函數一起使用,這樣聚集函數將作用於每個分組。

Hibernate <wbr>中HQL語句(一)     group by的用法為:

select 屬性1,屬性2,屬性,屬性n from 類名 group by 屬性m

Hibernate <wbr>中HQL語句(一)     其中屬性1,屬性2,屬性n必須滿足下列條件。

要么作為聚集函數的參數,要么為屬性m。例如,檢索各個系的學生的平均年齡:

select avg(s.sage),s.sdept from Student s group by s.sdept

其中字段s.sage作為平均值函數的參數,s.sdeptgroup by后的一個屬性。檢索的結果如下。

---------------------------------------------------------------------

化學系         21.0   

---------------------------------------------------------------------

計算機系       22.0   

---------------------------------------------------------------------

生物系         24.0   

---------------------------------------------------------------------

數學系         20.0   

---------------------------------------------------------------------

外語系         23.0   

檢索各個課程號與對應的選課人數。

select cno,count(sno) from SC s group by s.cno

1.1.18 having關鍵字

having關鍵字和group by關鍵字搭配使用,它對分組后的記錄進行篩選,輸出符合having指定條件的組。例如查詢人數超過1000人的系。

select s.sdept from Student s group by s.sdept having count(*)>1000

查詢男生人數多於500人的系。

select s.sdept from Student s where s.ssex=’M’ group by s.sdept having count(*)>500

Hibernate <wbr>中HQL語句(一)     以上面查詢男生人數多於500人的系為例:

select s.sdept from Student s where s.ssex=’M’ group by s.sdept having count(*)>500

查詢過程中同時使用group byhaving關鍵字時,查詢步驟如下。

1)檢索符合s.ssex=‘M’的所有男生。

2)根據s.sdept分組成不同的系。

3)對於每一個分組,計算分組中的記錄條數大於500的系。

4)將符合上述條件的s.sdept選出來。

Hibernate <wbr>中HQL語句(一)     wherehaving的區別在於作用對象不同。where作用於基本表,而having作用於分組后的組。

1.1.19 聚集函數

聚集函數包括count()avg()sum()max()min(),其含義如表6-1所示。

6-1         聚集函數及其含義

 

聚 集 函 數

    

count()

計算符合條件的記錄條數

avg()

計算符合條件的平均值

sum()

計算符合條件的和

max()

計算符合條件的最大值

min()

計算符合條件的最小值

Hibernate <wbr>中HQL語句(一)     各個函數的用法舉例如下。

檢索學生實例的對象個數:

select count(*) from Student

檢索計算機系的人數:

select count(*) from Student s where s.sdept='計算機系'

檢索學生實例的平均年齡:

select avg(s.sage) from Student s

檢索課程表course的所有課程的學分的總和:

select sum(c.ccredit) from Course c

檢索課程號為“1”的課程的最高成績:

select max(s.grade) from SC s where s.cno=1

檢索課程號為“1”的課程的最低成績:

select min(s.grade) from SC s where s.cno=1

Hibernate <wbr>中HQL語句(一)     聚集函數經常和group by分組關鍵字搭配使用。

檢索各門課程的平均成績:

select s.cno,avg(s.grade) from SC s group by s.cno

檢索各科不及格人數:

select s.cno,count(*) from SC s where s.grade<60 group by s.cno

 

 

 

 

1. 查詢整個映射對象所有字段

//直接from查詢出來的是一個映射對象,即:查詢整個映射對象所有字段  
         String hql = "from Users" ;  
         Query query = session.createQuery(hql);  
            
         List<Users> users = query.list();  
         for (Users user : users){  
             System.out.println(user.getName() + " : "  + user.getPasswd() + " : "  + user.getId());  
         }  
   
  輸出結果為:  
name1 : password1 : 1 
name2 : password2 : 2 
name3 : password3 : 3 

2.查詢字段  

//查詢其中幾個字段  
         String hql = " select name,passwd from Users" ;  
         Query query = session.createQuery(hql);  
         //默認查詢出來的list里存放的是一個Object數組  
         List<Object[]> list = query.list();  
         for (Object[] object : list){  
             String name = (String)object[ 0 ];  
             String passwd = (String)object[ 1 ];  
                
             System.out.println(name + " : "  + passwd);  
         }  
輸出結果為:  
name1 : password1  
name2 : password2  
name3 : password3 

 

3.修改默認查詢結果(query.list())不以Object[]數組形式返回,以List形式返回

//查詢其中幾個字段,添加new list(),注意list里的l是小寫的。也不需要導入包,這樣通過query.list()出來的list里存放的不再是默認的Object數組了,而是List集合了 
          String hql = " select new list(name,passwd) from Users" ;  
         Query query = session.createQuery(hql);  
         //默認查詢出來的list里存放的是一個Object數組,但是在這里list里存放的不再是默認的Object數組了,而是List集合了  
         List<List> list = query.list();  
         for (List user : list){  
             String name = (String)user.get( 0 );  
             String passwd = (String)user.get( 1 );  
                
             System.out.println(name + " : "  + passwd);  
         }  
         /** 
         輸出結果為: 
          name1 : password1 
         name2 : password2 
         name3 : password3 
          */ 

 

4.修改默認查詢結果(query.list())不以Object[]數組形式返回,以Map形式返回

//查詢其中幾個字段,添加new map(),注意map里的m是小寫的。也不需要導入包,這樣通過query.list()出來的list里存放的不再是默認的Object數組了,而是map集合了  
         String hql = " select new map(name,passwd) from Users" ;  
         Query query = session.createQuery(hql);  
         //默認查詢出來的list里存放的是一個Object數組,但是在這里list里存放的不再是默認的Object數組了,而是Map集合了  
         List<Map> list = query.list();  
         for (Map user : list){  
             //一條記錄里所有的字段值都是map里的一個元素,key是字符串0,1,2,3....,value是字段值  
             //如果將hql改為:String hql = " select new map(name as username,passwd as password) from Users";,那么key將不是字符串0,1,2...了,而是"username","password"了  
             String name = (String)user.get( "0" ); //get("0");是get(key),注意:0,1,2...是字符串,而不是整形  
             String passwd = (String)user.get( "1" );  
                
             System.out.println(name + " : "  + passwd);  
         }  
         /** 
         輸出結果為: 
          name1 : password1 
         name2 : password2 
         name3 : password3 
          */ 

 

5.修改默認查詢結果(query.list())不以Object[]數組形式返回,以自定義類型返回

 

6.條件查詢

//條件查詢,參數索引值從0開始,索引位置。通過setString,setParameter設置參數  
         String hql = "from Users where name=? and passwd=?" ;  
         Query query = session.createQuery(hql);  
         //第1種方式  
//      query.setString(0, "name1");  
//      query.setString(1, "password1");  
         //第2種方式  
         query.setParameter( 0 , "name1" ,Hibernate.STRING);  
         query.setParameter( 1 , "password1" ,Hibernate.STRING);  
         List<Users> list = query.list();  
         for (Users users : list){  
             System.out.println(users.getId());  
         }  

 

//條件查詢,自定義索引名(參數名):username,:password.通過setString,setParameter設置參數  
         String hql = "from Users where name=:username and passwd=:password" ;  
         Query query = session.createQuery(hql);  
         //第1種方式  
//      query.setString("username", "name1");  
//      query.setString("password", "password1");  
         //第2種方式,第3個參數確定類型  
         query.setParameter( "username" , "name1" ,Hibernate.STRING);  
         query.setParameter( "password" , "password1" ,Hibernate.STRING);  
         List<Users> list = query.list();  
         for (Users users : list){  
             System.out.println(users.getId());  
        

  

//條件查詢,通過setProperties設置參數  
         String hql = "from Users where name=:username and passwd=:password" ;  
         Query query = session.createQuery(hql);  
         //MyUser類的2個屬性必須和:username和:password對應  
         MyUser myUser = new  MyUser( "name1" , "password1" );  
         query.setProperties(myUser);  
         List<Users> list = query.list();  
         for (Users users : list){  
             System.out.println(users.getId());  
        

  

7.update 數據

           執行SQL語句(為什么要用SQL語句,我想是為了執行某些復雜的SQL語句吧) 

String sql= "update Table set field = 'test'"
Session session = HibernateSessionFactory.getSession();
session.createSQLQuery(sql).executeUpdate();
ts.commit();

 

     

   執行HQL語句   

String hql= "update Table set field = 'test'"
Session session = HiberanteSessionFactory.getSession();
Transaction ts = session.beginTransaction();
Query query = session.createQuery(hql);
query.executeUpdate();
ts.commit();


免責聲明!

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



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