Hibernate 作為全自動 ORM 框架,其核心思想是面向對象查詢。處理外鍵關聯時,不應直接操作外鍵列(如 tid),而應通過對象導航屬性(如 teacher.id)構建 HQL,讓框架自動轉換為高效 SQL。本文通過實例對比錯誤與正確寫法,並展示 DAO 封裝模式,實現基於外鍵的靈活查詢。
// 錯誤:直接使用外鍵列名 tid,繞過對象模型
String hql = "SELECT s.name FROM Student s WHERE s.tid = " + teacher.getId();
缺點:破壞對象模型完整性,耦合數據庫結構,難以維護,無法利用 Hibernate 緩存與關聯導航。
// 正確:通過 Student 對象的 teacher 關聯屬性導航到 Teacher 的 id
String hql = "SELECT s.name FROM Student s WHERE s.teacher.id = :teacherId";
Query query = session.createQuery(hql);
query.setParameter("teacherId", teacher.getId());
List names = query.list();
優勢:符合 ORM 思想,自動生成帶關聯條件的 SQL,支持參數綁定防注入,可移植性強。
假設 Comment 表有外鍵 bk_id 關聯 Book,Hibernate 映射中 Comment 類無 bkId 屬性,而是 Book book 對象引用。
public List findByProperty(String propertyName, Object value) {
String hql = "FROM Reply r WHERE r." + propertyName + " = ?";
Query query = getSession().createQuery(hql);
query.setParameter(0, value);
return query.list();
}
// DAO 層
public List findCommentByBook(Book book) {
return findByProperty("book", book); // 直接傳遞 Book 對象
}
// Service 層調用
Book book = new Book();
book.setBkId(bookId); // 僅設置主鍵即可,Hibernate 只會用到 id 欄位
List comments = dao.findCommentByBook(book);
核心原理:Hibernate 解析 HQL 時,遇到 WHERE r.book = ? 且參數為 Book 對象,會自動提取其主鍵值生成 WHERE r.bk_id = ? SQL。因此構造查詢參數時,只需設置關聯對象的主鍵屬性,其他屬性可忽略。
對於複雜多條件查詢,推薦使用 Criteria API,類型安全且可動態組裝:
Criteria criteria = session.createCriteria(Comment.class);
criteria.add(Restrictions.eq("book.id", bookId)); // 直接針對關聯對象主鍵
List list = criteria.list();
student.teacher.id)而非外鍵列名構建 HQL。findByProperty,業務層傳遞關聯對象(僅設置主鍵)。