Hibernate HQL查詢解析
在HQL中關(guān)鍵字不區(qū)分大小寫,但是屬性和類名區(qū)分大小寫,下面介紹各種類型的Hibernate的HQL查詢。
1、Hibernate HQL查詢:簡單屬性查詢
* 單一屬性查詢,返回結(jié)果集屬性列表,元素類型和實體類中相應(yīng)的屬性類型一致
* 多個屬性查詢,返回的集合元素是對象數(shù)組,數(shù)組元素的類型和對應(yīng)的屬性在實體類中的類型一致
數(shù)組的長度取決與select中屬性的個數(shù)
* 如果認為返回數(shù)組不夠?qū)ο蠡梢圆捎肏QL動態(tài)實例化Student對象
2、Hibernate HQL查詢:實體對象查詢
* N + 1問題,在默認情況下,使用query.iterate查詢,有可以能出現(xiàn)N+1問題,所謂的N+1是在查詢的時候發(fā)出了N+1條sql語句,1: 首先發(fā)出一條查詢對象id列表的sql,N: 根據(jù)id列表到緩存中查詢,如果緩存中不存在與之匹配的數(shù)據(jù),那么會根據(jù)id發(fā)出相應(yīng)的sql語句
* list和iterate的區(qū)別?
* list每次都會發(fā)出sql語句,list會向緩存中放入數(shù)據(jù),而不利用緩存中的數(shù)據(jù)
* iterate:在默認情況下iterate利用緩存數(shù)據(jù),但如果緩存中不存在數(shù)據(jù)有可以能出現(xiàn)N+1問題
3、Hibernate HQL查詢:條件查詢
* 可以采用拼字符串的方式傳遞參數(shù)
Java代碼:
- List students = session.createQuery
- ("select s.id, s.name from Student s where s.name like '%1%'").list();
* 可以采用 ?來傳遞參數(shù)(索引從0開始)
Java代碼:
- List students = session.createQuery
- ("select s.id, s.name from Student s where s.name like ?").setParameter(0, "%1%").list();
- //可以使用?方式傳遞參數(shù)
- //參數(shù)的索引從0開始
- //傳遞的參數(shù)值,不用單引號引起來
- //注意方法鏈編程
* 可以采用 :參數(shù)名 來傳遞參數(shù)
Java代碼:
- List students = session.createQuery
- ("select s.id, s.name from Student s where s.name like :myname").
- setParameter("myname", "%1%").list();
* 如果傳遞多個參數(shù),可以采用setParamterList方法
Java代碼:
- List students = session.createQuery
- ("select s.id, s.name from Student s where s.id in(:myids)").
- setParameterList("myids", new Object[]{1, 2, 3, 4, 5}).list();
* 在HQL中可以使用數(shù)據(jù)庫的函數(shù),如:date_format
Java代碼:
- List students = session.createQuery
- ("select s.id, s.name from Student s where date_format(s.createTime, '%Y-%m')=?").
- setParameter(0, "2008-02").list();
- SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
- //查詢2008-01-10到2008-02-15創(chuàng)建的學生
- List students = session.createQuery
- ("select s.id, s.name from Student s where s.createTime between ? and ?")
- .setParameter(0, sdf.parse("2008-01-10 00:00:00"))
- .setParameter(1, sdf.parse("2008-02-15 23:59:59"))
- .list();
4、Hibernate HQL查詢:直接使用sql進行查詢
Java代碼:
- List students = session.createSQLQuery("select * from t_student").list();
不會返回對象,而是所有屬性!
5、Hibernate HQL查詢:分頁查詢
* setFirstResult(),從0開始
* setMaxResults,每頁顯示多少條數(shù)據(jù)
Java代碼:
- List students = session.createQuery("from Student")
- .setFirstResult(1)
- .setMaxResults(2)
- .list();
6、Hibernate HQL查詢:對象導航查詢,在HQL中采用 . 進行導航
7、Hibernate HQL查詢:連接查詢
* 內(nèi)連
Sql代碼:
- SELECT s.name, c.name FROM Student s (inner) join s.classes c
* 外連接(左連接/右連接)
Sql代碼:
- SELECT s.name, c.name FROM Student s left join s.classes c
8、Hibernate HQL查詢:統(tǒng)計查詢
Java代碼:
- List students =session.createQuery
- ("select c.name, count(s) from Student s join s.classes c "
- +"group by c.name order by c.name").list();
- for (Iterator iter=students.iterator(); iter.hasNext();) {
- Object[] obj = (Object[])iter.next();
- System.out.println(obj[0] + ", " + obj[1]);
- }
9、DML風格的操作(盡量少用,因為和緩存不同步)
Java代碼:
- session.createQuery
- ("update Student s set s.name=? where s.id < ?")
- .setParameter(0, "李四")
- .setParameter(1, 5)
- .executeUpdate();
應(yīng)當盡量少用,因為和緩存不同步,也就是說,假如在執(zhí)行上面的語句之前,已經(jīng)把student封裝成一個list曾經(jīng)拿了出來,再執(zhí)行上面的語句對 student中的表進行數(shù)據(jù)更新,然后再list Student表,則此時的list是從緩存中取的數(shù)據(jù),而不是從表中找到的數(shù)據(jù),也就是說,list拿到的是update前的數(shù)據(jù),所以造成了這種不同步,所以這種風格盡量少用。
從這個方面也可以看得出Hibernate并不適用于聚集性,統(tǒng)計,大量批量的更新,刪除等操作。
【編輯推薦】

















