首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Hibernate 分頁查詢代碼詳解:動態構建 HQL 與 Session 管理

     編輯:程式設計綜合問答

代碼結構概覽

提供了兩個核心方法:getList(業務入口,構建條件)和 findAll(執行分頁 HQL 查詢)。

public List getList(String startTime, String endTime, String mc, Pager pager) {
    String where = " ";
    where = where + " and " + TypeChange.DateBetweenSql("a.riQi", startTime, endTime);
    if (!TypeChange.toNotNullDao(mc).equals("")) {
        where = where + " and a.mingCheng like '%" + TypeChange.toNotNullNullDao(mc) + "%'";
    }
    return this.findAll(where, pager);
}

private List<Test> findAll(String where, Pager pager) {
    String hSql = " From Test a where 1=1 " + where + " order by id ";
    pager.setRowCount(getAllRowCount(hSql));
    Session sess = this.getSessionFactory().openSession();
    try {
        Query query = sess.createQuery(hSql);
        query.setFirstResult(pager.getFirstResult());
        query.setMaxResults(pager.getPageSize());
        return query.list();
    } finally {
        sess.close();
    }
}

逐行邏輯解析

1. getList — 動態構建 WHERE 子句

  • String where = " ":初始化為包含一個空格的字符串,確保後續拼接 and ... 時語法正確(避免 where 1=1and...)。
  • TypeChange.DateBetweenSql("a.riQi", startTime, endTime):工具方法生成日期範圍條件,如 a.riQi between '2023-01-01' and '2023-12-31'。拼接後 where = " and a.riQi between ..."。
  • TypeChange.toNotNullDao(mc):工具方法處理 null/空字符串,返回安全字符串。
  • like '%...%':模糊查詢,匹配包含關鍵字的記錄。
  • 最終 where 可能為 " and a.riQi between ... and a.mingCheng like '%xxx%'" 或僅含日期條件。

2. findAll — 執行分頁 HQL 查詢

  • String hSql = " From Test a where 1=1 " + where + " order by id ":
    • From Test a:HQL 查詢實體 Test,別名 a。
    • where 1=1:經典技巧,確保後續拼接的 and ... 語法始終合法,即使 where 為空也無語法錯誤。
    • order by id:按主鍵排序,保證分頁結果穩定。
  • pager.setRowCount(getAllRowCount(hSql)):執行單獨的計數查詢(select count(*) ...)獲取總記錄數,設置到分頁對象,用於計算總頁數。
  • Session sess = this.getSessionFactory().openSession():打開新 Session(非當前線程綁定的 getCurrentSession),需手動關閉。
  • Query query = sess.createQuery(hSql):創建 HQL 查詢對象。
  • query.setFirstResult(pager.getFirstResult()):設置起始行(offset),如第 2 頁每頁 10 條 → firstResult=10。
  • query.setMaxResults(pager.getPageSize()):設置最大返回行數(limit)。
  • return query.list():執行查詢並返回實體列表。
  • finally { sess.close() }:**必須在 finally 中關閉 Session**,防止連接洩漏,即使查詢拋異常也能釋放資源。

潛在問題與改進建議

  1. SQL 注入風險:where 直接拼接字符串,mc 經 toNotNullDao 處理但未做參數化。建議改用**命名參數**:
    query.setParameter("mc", "%" + mc + "%"),HQL 中寫 and a.mingCheng like :mc。
  2. 日期參數化:同理,日期條件應用參數綁定,避免格式差異導致錯誤。
  3. Session 管理:若在 Spring 管理的事務中,應用 getCurrentSession() 配合 @Transactional,由容器管理生命週期,無需手動 open/close。
  4. 計數查詢優化:getAllRowCount 應構造 select count(a) From Test a where 1=1 ... 而非查全表再數。
  5. 泛型擦除:返回 List 原始類型,建議改為 List<Test>。

總結

這段代碼展示了經典的 **Hibernate 手動分頁查詢模式**:動態拼接 HQL 片段 → 計總數 → 開 Session → 設置分頁參數 → 執行查詢 → 關 Session。理解 where 1=1 技巧、setFirstResult/setMaxResults 分頁機制、以及 finally 保證資源釋放,是掌握 Hibernate 底層操作的關鍵。實際項目中建議優先使用 Spring Data JPA / MyBatis-Plus 等框架內置的分頁能力,減少樣板代碼與風險。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved