HQL (Hibernate Query Language) 是面向對象的查詢語言,操作的是持久化類及其屬性,而非數據庫表和列。本文系統梳理 HQL 核心語法、聚合分組、參數綁定、子查詢等實戰技巧。
// 查詢所有學生對象
List<Student> list = session.createQuery("from Student").list();
// 唯一結果查詢(高效,避免列表開銷)
Student s = (Student) session.createQuery("from Student where sid='20050003'").uniqueResult();
// 查詢指定屬性,返回 Object[] 數組
List<Object[]> list = session.createQuery("select distinct sage, ssex from Student").list();
for (Object[] objs : list) {
System.out.println(objs[0] + " " + objs[1]);
}
// Between
List<Object[]> list = session.createQuery("select sage, ssex, sname from Student where sage between 20 and 22").list();
// IN / NOT IN
List<Student> list = session.createQuery("from Student where sdept in ('計算機系','外語系')").list();
// 各系平均年齡
List<Object[]> list = session.createQuery("select avg(sage), sdept from Student group by sdept").list();
// 人數大於 3 的系
List<Object[]> list = session.createQuery("select count(*) as c1, sdept from Student group by sdept having count(*) > 3").list();
// 計算機系人數(單列聚合返回 List<Object> 而非 Object[])
List<Object> list = session.createQuery("select count(*) from Student where sdept='計算機系'").list();
命名參數(推薦,可讀性強)
Query q = session.createQuery("from Student where sdept=:dept and sage > :age");
List<Student> list = q.setString("dept", "計算機系").setInteger("age", 20).list();
位置參數(JDBC 風格)
Query q = session.createQuery("from Student where sdept=? and sage > ?");
List<Student> list = q.setString(0, "計算機系").setInteger(1, 20).list();
分開綁定
Query query = session.createQuery("from Student where sdept=? and sage > ?");
query.setString(0, "計算機系");
query.setInteger(1, 20);
List<Student> list = query.list();
思路:通過用戶名查詢數據庫中存儲的密碼哈希,再與用戶輸入的密碼哈希比對,而非拼接 SQL。但參數綁定是標準、最安全、最高效的方案,無需重複造輪子。
// 子查詢:查詢選修 11 號課程的最高/最低分
List<Object[]> list = session.createQuery(
"select 11, max(grade), min(grade) from Studcourse where course.cid = 11").list();
// 隱式內連接(導航屬性)
List<Object[]> list = session.createQuery(
"select count(*), student.sdept from Studcourse where grade < 60 group by student.sdept").list();
| 特性 | HQL | SQL |
|---|---|---|
| 面向 | 類/屬性 | 表/列 |
| 大小寫敏感 | 類名/屬性名敏感,關鍵字不敏感 | 視數據庫而定 |
| 多態查詢 | 支持 from Animal 查詢所有子類 | 不支持 |
| 分頁 | query.setFirstResult().setMaxResults() | 方言相關 (LIMIT/ROWNUM/OFFSET) |
| 返回類型 | 實體、Object[]、List、Map、標量 | ResultSet |