Hibernate Query Language (HQL) 是面向物件的查詢語言,語法類似 SQL 但操作的是實體類與屬性。掌握 HQL 能讓資料存取更彈性、更符合物件導向思維。
最基本的查詢是取得完整實體物件:
String hql = "from TUser";
這會回傳 TUser 及其子類別的所有記錄。注意: 若實體類別包含外鍵關聯,直接查詢可能拋出異常。解決方式是使用別名並明確選取屬性:
String hql = "select user from TUser as user";
若寫成 select user.name from TUser user 則屬於屬性查詢,不會觸發外鍵載入問題。
特殊用法:from java.lang.Object 可掃描資料庫中所有對應表的資料,適合除錯或全庫掃描。
支援標準比較運算子(=, <>, >, <, >=, <=, between, in, like 等):
String hql = "from TUser user where user.name = 'yyy'";
as 關鍵字可省略,TUser user 等同 TUser as user。
僅選取特定欄位,回傳 Object[] 陣列:
List list = session.createQuery("select user.name, user.age from TUser user").list();
利用建構子表達式直接封裝成實體(需類別提供對應建構子):
List list = session.createQuery("select new TUser(user.name, user.age) from TUser user").list();
Iterator it = list.iterator();
while (it.hasNext()) {
TUser user = (TUser) it.next();
System.out.println(user.getName()); // 僅 name、age 有值,其他屬性為 null
}
警告: 這樣建構的物件僅供讀取,不可用於更新操作。
支援 count, min, max, sum, avg 等統計函數:
"select count(*), min(user.age) from TUser user"
使用 distinct 移除重複列:
"select distinct user.name from TUser user"
無需先載入實體,直接執行大量資料操作:
// 更新
Query query = session.createQuery("update TUser set age=18 where id=1");
query.executeUpdate();
// 刪除
session.createQuery("delete TUser where age >= 18").executeUpdate();
// 排序
from TUser user order by user.name, user.age desc
// 分組 + Having
"select count(user), user.age from TUser user group by user.age having count(user) > 10"
位置參數 (?):
Query query = session.createQuery("from TUser where name=? and age>?");
query.setString(0, "Erica");
query.setInteger(1, 20);
命名參數 (:name):可讀性更佳:
String hql = "from TUser where name=:name";
Query query = session.createQuery(hql);
query.setParameter("name", "Erica");
POJO 封裝參數:自動對應 getter:
class UserQuery { private String name; private Integer age; /* getter/setter */ }
UserQuery uq = new UserQuery(); uq.setName("Erica"); uq.setAge(20);
query.setProperties(uq); // 內部自動呼叫 getName(), getAge()
支援 inner join, left outer join, right outer join, full join。舊式笛卡兒積寫法 from TUser, TAddress 仍可用,但建議改用明確 JOIN 語法以利維護。