HQL (Hibernate Query Language) 是面向物件的查詢語言,支援多種參數綁定方式、導航查詢、分頁、資料庫函數呼叫及原生 SQL。本文以 Student 實體為例,系統展示 8 種常用查詢模式。
class Student {
Long id;
String name;
Date createTime;
Classes classes; // 關聯實體
}
List students = session.createQuery(
"select s.id, s.name from Student s where s.name like '%1'").list();
for (Object[] o : students) System.out.println(o[0] + "," + o[1]);
List students = session.createQuery(
"select s.id, s.name from Student s where s.name like :goodname")
.setParameter("goodname", "%1%").list();
List students = session.createQuery(
"select s.id, s.name from Student s where s.name like ?")
.setParameter(0, "%1%").list(); // 索引從 0 開始
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,32,13,14}).list();
List students = session.createQuery(
"select s.id, s.name from Student s where date_format(s.createTime, '%Y-%m') = ?")
.setParameter(0, "2008-10").list();
// date_format 為 MySQL 函數,跨資料庫需注意方言
List students = session.createSQLQuery("select * from t_student").list();
// 回傳 Object[],欄位順序對應資料表定義
List names = session.createQuery(
"select s.name from Student s where s.classes.name like '%1%'").list();
// 自動產生 INNER JOIN,無需手寫 JOIN 子句
List students = session.createQuery("from Student")
.setFirstResult(0).setMaxResults(3).list();
// 相當於 LIMIT 0,3 (MySQL) 或 ROWNUM (Oracle)
query.setCacheable(true) 搭配二級快取提升重複查詢效能select new DTO(s.id, s.name) from Student s 直接映射至 DTO,避免 Object[]@BatchSize(size=10) 減少 N+1 問題| 場景 | 建議做法 |
|---|---|
| 動態條件查詢 | Criteria API 或 JPA Specification |
| 固定報表查詢 | 命名 HQL + 快取 |
| 大量資料分頁 | 游標/Keyset 分頁 (避免 OFFSET 深分頁效能劣化) |
| 跨資料庫函數 | 定義 Dialect 擴充函數,或改用原生 SQL |