《Java從入門到放棄》入門篇:hibernate查詢——HQL


不知不覺又到了hibernate的最后一篇了,只感覺時光飛逝~,歲月如梭~!

轉眼之間,我們就···························,好吧,想裝個X,結果裝不下去了,還是直接開始吧·j_0009.gif

 

前面我們已經把hibernate中添加、刪改、修改和根據ID得到對象的方法都學習了,但如何才能查詢出多條記錄呢?比如我想查詢所有姓黃的作者,查詢標題包含“中”字的博客等。這一篇就來介紹查詢。

hibernate有兩種檢索(查詢)數據的方式,分別是HQL(Hibernate Query Language)和QBC(Query By Criteria)。官方推薦使用HQL的方式,不要問我為什么,因為············就算你很誠懇的詢問我,我也不會告訴你。反正用過HQL的人都說好。j_0018.gif

 

HQL提供的語法與SQL非常相似,支持動態參數綁定、投影查詢、分頁查詢、連接查詢、分組查詢、內置聚集函數、子查詢等,可以說是數據庫中常用的查詢功能,HQL都可以實現。

當然,HQL並不是只能查詢,其實也可以用來執行insert、delete和update語句(使用HQL語法),只不過我們今天不講,大家有興趣自己練習一下就OK了。

 

HQL使用步驟:

  1. )獲取Session對象

  2. )編寫HQL語句

  3. )獲得Query對象

  4. )動態綁定參數

  5. )調用執行方法

 

今天玩點花樣,我們通過常用的查詢功能來講解每個語法吧。

一、查詢所有的作者

1
2
3
4
5
6
7
8
9
10
11
     public  static  void  main(String[] args) {
         Session session = HibernateSessionFactory.getSession();
         //查詢所有作者
         String hql =  "from Author" ;
         Query query = session.createQuery(hql);
         List<Author> list = query.list();
         for  (Author author : list) {
             System.out.println( "姓名:" +author.getUsername());
         }
         HibernateSessionFactory.closeSession();
     }

注意:

1. 查詢Author的所有屬性時可以省略select部分

2. from后面的Author是Java中的實體類的類名,在HQL語句中 select或from之類的關鍵字不區別大小寫,但類名、屬性名必須和實體類大小寫完全相同。

結果:

wKioL1maoBzAkxlJAABLi7iJhF0201.png

 

二、查詢作者ID為2的所有博客

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
     public  static  void  main(String[] args) {
         Session session = HibernateSessionFactory.getSession();
         //查詢ID為2的作者的博客
         Author author = (Author)session.get(Author. class 2 );
         //把作者對象當作參數進行查詢
         //String hql = "from Blog b where b.author=?";     //占位符方式
         String hql =  "from Blog b where b.author=:author" ;    //參數名方式
         Query query = session.createQuery(hql);
         //添加參數
         //query.setEntity(0, author);      //占位符方式
         query.setEntity( "author" , author);    //參數名方式
         //執行查詢
         List<Blog> list = query.list();
         //遍歷結果
         for  (Blog blog : list) {
             System.out.println( "標題:" +blog.getTitle());
         }
         HibernateSessionFactory.closeSession();
     }

注意:

這兒的條件,where后面的author是Blog實體類中的author屬性,參數是什么類型就可以使用setxxx傳對應的類型

參數有兩種寫法:一種是使用“?”,相當於占位符,另一種使用“:xxx”,相當於根據名字傳值。

結果:

wKiom1mapzCSTLN9AAB8SWG4kus870.png

 

三、查詢標題包含“中”字的所有博文

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
     public  static  void  main(String[] args) {
         Session session = HibernateSessionFactory.getSession();
         //查詢標題包含“中”字的所有博文
         String hql =  "from Blog b where b.title like ?" ;
         Query query = session.createQuery(hql);
         //添加參數
         query.setString( 0 "%中%" );     //參數名方式
         //執行查詢
         List<Blog> list = query.list();
         //遍歷結果
         for  (Blog blog : list) {
             System.out.println( "標題:" +blog.getTitle());
         }
         HibernateSessionFactory.closeSession();
     }

注意:

like后面不能寫成'%?%',這種寫法是錯誤的。必須在外面拼接好前后的“%”,再作為參數傳遞給query對象。

結果:

wKioL1maqKKzPiBkAABR5a3RCnE467.png

 

四、按博文創建日期倒序排列所有博文

1
2
3
4
5
6
7
8
9
10
11
12
13
     public  static  void  main(String[] args) {
         Session session = HibernateSessionFactory.getSession();
         //按日期倒序排列所有博文
         String hql =  "from Blog b order by b.createTime desc" ;
         Query query = session.createQuery(hql);
         //執行查詢
         List<Blog> list = query.list();
         //遍歷結果
         for  (Blog blog : list) {
             System.out.println( "時間:" +blog.getCreateTime()+ ",標題:" +blog.getTitle());
         }
         HibernateSessionFactory.closeSession();
     }

注意:

反復看了三遍,發現真的沒有哪兒需要注意,我也很絕望啊!j_0041.gif

結果:

wKioL1mbgt2jqkMBAAB0Clw4ys4183.png

 

五、假如每頁顯示3篇博文,在上一查詢的基礎上,查詢第2頁的博文

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
     public  static  void  main(String[] args) {
         Session session = HibernateSessionFactory.getSession();
         int  pageNO =  2 ;        //頁碼
         int  pageCount =  3 ;     //每頁數量
         //按日期倒序排列所有博文
         String hql =  "from Blog b order by b.createTime desc" ;
         Query query = session.createQuery(hql);
         query.setFirstResult((pageNO- 1 )*pageCount);         //起始位置
         query.setMaxResults(pageCount);                     //記錄數量
         //執行查詢
         List<Blog> list = query.list();
         //遍歷結果
         for  (Blog blog : list) {
             System.out.println( "時間:" +blog.getCreateTime()+ ",標題:" +blog.getTitle());
         }
         HibernateSessionFactory.closeSession();
     }

注意:

setFirstResult表示查詢的第一條記錄的下標,setMaxResults表示查詢幾條記錄,一般分頁都是傳遞頁碼(第幾頁)過來。至於實際項目中的分頁如何編寫,等后面我們講常用功能模塊時再來說明吧。

結果:

wKioL1mbhauTNs3xAABcpSt3TTI619.png

 

六、根據手機號查詢作者(確定最多只有一條記錄)

1
2
3
4
5
6
7
8
9
10
11
12
     public  static  void  main(String[] args) {
         Session session = HibernateSessionFactory.getSession();
         //查詢手機號為13612349876的作者
         String hql =  "from Author a where a.phone=?" ;
         Query query = session.createQuery(hql);
         //添加參數
         query.setString( 0 "13612349876" );
         //執行查詢
         Author author = (Author)query.uniqueResult();
         System.out.println( "姓名:" +author.getUsername()+ ",聯系方式:" +author.getPhone());
         HibernateSessionFactory.closeSession();
     }

注意:

確定查詢結果最多只有一條記錄時,可以使用uniqueResult()方法。

結果:

wKioL1mbimyBWU-pAABSEnG8iGY981.png

 


單表查詢並且返回所有屬性的查詢語法,到這兒就告一段落。

接下來進行部分屬性的查詢、分組查詢、多表查詢和子查詢。


 

查詢語法加上select子句后,返回的結果有以下幾種接收方式。

  1. object[]數組

  2. List集合

  3. Map集合

  4. 自定義實體類

我們還是通過例子來學習吧:查詢所有博文,只返回標題和內容。

1
2
3
4
5
6
7
8
9
10
11
     public  static  void  main(String[] args) {
         Session session = HibernateSessionFactory.getSession();
         //查詢所有博文,返回標題和內容
         String hql =  "select title,content from Blog" ;
         Query query = session.createQuery(hql);
         List<Blog> list = query.list();
         for  (Blog blog : list) {
             System.out.println( "標題:" +blog.getTitle());
             System.out.println( "\t內容:" +blog.getContent());
         }
     }

運行會發現出現以下異常:

wKiom1mbkevjbSidAAAcv3z7oJM710.png

大概意思就是不能把Object轉換成Blog類型。

接下來,我們使用上面所說的四種方式來解決這個問題,結果就不再一一展示了。j_0038.gif

1、Object[]數組方式

1
2
3
4
5
6
7
8
9
10
11
12
13
     public  static  void  main(String[] args) {
         Session session = HibernateSessionFactory.getSession();
         //查詢所有博文,返回標題和內容
         String hql =  "select title,content from Blog" ;
         Query query = session.createQuery(hql);
         //執行查詢
         List<Object[]> list = query.list();
         for  (Object[] objects : list) {
             System.out.println( "標題:" +objects[ 0 ]);
             System.out.println( "\t內容:" +objects[ 1 ]);
         }
         HibernateSessionFactory.closeSession();
     }

注意:如果只查詢一個屬性時,返回的就不再在數組,而是單個Object。

 

2、List集合方式

1
2
3
4
5
6
7
8
9
10
11
12
13
     public  static  void  main(String[] args) {
         Session session = HibernateSessionFactory.getSession();
         //查詢所有博文,返回標題和內容
         String hql =  "select new List(title,content) from Blog" ;
         Query query = session.createQuery(hql);
         //執行查詢
         List<List> list = query.list();
         for  (List lst : list) {
             System.out.println( "標題:" +lst.get( 0 ));
             System.out.println( "\t內容:" +lst.get( 1 ));
         }
         HibernateSessionFactory.closeSession();
     }

注意:HQL語句中的select后面,使用new List()的方式來接受數據。

 

3、Map集合方式

1
2
3
4
5
6
7
8
9
10
11
12
13
     public  static  void  main(String[] args) {
         Session session = HibernateSessionFactory.getSession();
         //查詢所有博文,返回標題和內容
         String hql =  "select new Map(title as t,content as c) from Blog" ;
         Query query = session.createQuery(hql);
         //執行查詢
         List<Map> list = query.list();
         for  (Map map : list) {
             System.out.println( "標題:" +map.get( "t" ));
             System.out.println( "\t內容:" +map.get( "c" ));
         }
         HibernateSessionFactory.closeSession();
     }

注意:如果new Map()中的屬性沒有取別名,則在for循環中通過get("下標")的形式來讀取數據,特別注意,這兒是字符串"下標",而不是整數。

 

4、自定義實體類

4.1)在Blog實體類中添加包含標題和內容的構造方法

1
2
3
4
5
     //新增構造方法
     public  Blog(String title, String content){
         this .title = title;
         this .content = content;
     }

4.2)測試類中的代碼

1
2
3
4
5
6
7
8
9
10
11
12
13
     public  static  void  main(String[] args) {
         Session session = HibernateSessionFactory.getSession();
         //查詢所有博文,返回標題和內容
         String hql =  "select new Blog(title,content) from Blog" ;
         Query query = session.createQuery(hql);
         //執行查詢
         List<Blog> list = query.list();
         for  (Blog blog : list) {
             System.out.println( "標題:" +blog.getTitle());
             System.out.println( "\t內容:" +blog.getContent());
         }
         HibernateSessionFactory.closeSession();
     }

注意:HQL語句中查詢幾個屬性,則在對應的實體類中必須的對應的構造方法。

四種方式到這兒就介紹完畢,至於哪種好哪種差,那就看個人習慣了。

 

繼續后面的案例:

七、查詢每個作者的博文數量(分組查詢)

1
2
3
4
5
6
7
8
9
10
11
12
13
     public  static  void  main(String[] args) {
         Session session = HibernateSessionFactory.getSession();
         //查詢每個作者的博文數
         String hql =  "select author, count(b) from Blog b group by b.author" ;
         Query query = session.createQuery(hql);
         //執行查詢
         List<Object[]> list = query.list();
         for  (Object[] objects : list) {
             System.out.print( "作者:" +((Author)objects[ 0 ]).getUsername());
             System.out.println( ",博文數:" +objects[ 1 ]);
         }
         HibernateSessionFactory.closeSession();
     }

注意:分組之后的統計數據沒辦法保存到實體類,所以只能使用前三種方式來接受數據。

結果:

wKioL1mbnF6y8aIkAABwMSv5QVA030.png

八、查詢所有的博文和作者(作者賬號已經注銷的不查(也就是博文表中作者ID為null的不查),多表聯合查詢)

1
2
3
4
5
6
7
8
9
10
11
12
13
     public  static  void  main(String[] args) {
         Session session = HibernateSessionFactory.getSession();
         //查詢所有博文,包括作者信息
         String hql =  "from Blog b inner join b.author a" ;
         Query query = session.createQuery(hql);
         //執行查詢
         List<Object[]> list = query.list();
         for  (Object[] objs : list) {
             System.out.println( "標題:" +((Blog)objs[ 0 ]).getTitle());
             System.out.println( "\t作者:" +((Author)objs[ 1 ]).getUsername());
         }
         HibernateSessionFactory.closeSession();
     }

注意:inner join后面的是Blog類中的author屬性,Ojbect[]數組中保存的是兩個對象。左連接的功能,大家自己嘗試吧。

結果:

wKiom1mbofKgrCKXAAAs2_3OvKw962.png

 

九、最后一個,查詢博文數是2的所有作者(子查詢)

1
2
3
4
5
6
7
8
9
10
11
12
     public  static  void  main(String[] args) {
         Session session = HibernateSessionFactory.getSession();
         //查詢所有博文,包括作者信息
         String hql =  "from Author a where (select count(b) from a.blogs b)=2" ;
         Query query = session.createQuery(hql);
         //執行查詢
         List<Author> list = query.list();
         for  (Author author : list) {
             System.out.println( "作者:" +author.getUsername());
         }
         HibernateSessionFactory.closeSession();
     }

結果:

wKiom1mbosmg_gSnAABkNnn02Ug040.png

呼~~~~~~j_0039.gif,想不到我也能寫出這么長的文章。

破了我30多年來的歷史記錄啊!!!激動得要j_0041.gif了。

懇請大大給我加個推薦吧~~j_0002.gif

 

“軟件思維”博客地址:51CTO博客園,感興趣的小伙伴可以去看相關的其它博文。

 


免責聲明!

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



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