不知不覺又到了hibernate的最后一篇了,只感覺時光飛逝~,歲月如梭~!
轉眼之間,我們就···························,好吧,想裝個X,結果裝不下去了,還是直接開始吧·
前面我們已經把hibernate中添加、刪改、修改和根據ID得到對象的方法都學習了,但如何才能查詢出多條記錄呢?比如我想查詢所有姓黃的作者,查詢標題包含“中”字的博客等。這一篇就來介紹查詢。
hibernate有兩種檢索(查詢)數據的方式,分別是HQL(Hibernate Query Language)和QBC(Query By Criteria)。官方推薦使用HQL的方式,不要問我為什么,因為············就算你很誠懇的詢問我,我也不會告訴你。反正用過HQL的人都說好。
HQL提供的語法與SQL非常相似,支持動態參數綁定、投影查詢、分頁查詢、連接查詢、分組查詢、內置聚集函數、子查詢等,可以說是數據庫中常用的查詢功能,HQL都可以實現。
當然,HQL並不是只能查詢,其實也可以用來執行insert、delete和update語句(使用HQL語法),只不過我們今天不講,大家有興趣自己練習一下就OK了。
HQL使用步驟:
-
)獲取Session對象
-
)編寫HQL語句
-
)獲得Query對象
-
)動態綁定參數
-
)調用執行方法
今天玩點花樣,我們通過常用的查詢功能來講解每個語法吧。
一、查詢所有的作者
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之類的關鍵字不區別大小寫,但類名、屬性名必須和實體類大小寫完全相同。
結果:
二、查詢作者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”,相當於根據名字傳值。
結果:
三、查詢標題包含“中”字的所有博文
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對象。
結果:
四、按博文創建日期倒序排列所有博文
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();
}
|
注意:
結果:
五、假如每頁顯示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表示查詢幾條記錄,一般分頁都是傳遞頁碼(第幾頁)過來。至於實際項目中的分頁如何編寫,等后面我們講常用功能模塊時再來說明吧。
結果:
六、根據手機號查詢作者(確定最多只有一條記錄)
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()方法。
結果:
單表查詢並且返回所有屬性的查詢語法,到這兒就告一段落。
接下來進行部分屬性的查詢、分組查詢、多表查詢和子查詢。
查詢語法加上select子句后,返回的結果有以下幾種接收方式。
-
object[]數組
-
List集合
-
Map集合
-
自定義實體類
我們還是通過例子來學習吧:查詢所有博文,只返回標題和內容。
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());
}
}
|
運行會發現出現以下異常:
大概意思就是不能把Object轉換成Blog類型。
接下來,我們使用上面所說的四種方式來解決這個問題,結果就不再一一展示了。
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();
}
|
注意:分組之后的統計數據沒辦法保存到實體類,所以只能使用前三種方式來接受數據。
結果:
八、查詢所有的博文和作者(作者賬號已經注銷的不查(也就是博文表中作者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[]數組中保存的是兩個對象。左連接的功能,大家自己嘗試吧。
結果:
九、最后一個,查詢博文數是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();
}
|
結果:
呼~~~~~~,想不到我也能寫出這么長的文章。
破了我30多年來的歷史記錄啊!!!激動得要了。
“軟件思維”博客地址:51CTO,博客園,感興趣的小伙伴可以去看相關的其它博文。