Spring 的 HibernateTemplate 預設不直接支援分頁,但透過 HibernateCallback 取得原生 Session 即可輕鬆實現。以下是通用分頁查詢方法:
/**
* HQL 分頁查詢
* @param hql HQL 查詢語句
* @param offset 起始記錄索引(從 0 開始)
* @param length 每頁筆數
* @return 結果列表
*/
public List getListForPage(final String hql, final int offset, final int length) {
return getHibernateTemplate().executeFind(new HibernateCallback() {
public Object doInHibernate(Session session) throws HibernateException, SQLException {
Query query = session.createQuery(hql);
query.setFirstResult(offset); // 相當於 LIMIT offset
query.setMaxResults(length); // 相當於 LIMIT length
return query.list();
}
});
}
setFirstResult(int):設定起始行(0 基礎),對應 SQL OFFSET 或 MySQL LIMIT offset。setMaxResults(int):設定最大回傳行數,對應 SQL LIMIT length 或 TOP。executeFind 自動管理 Session 生命週期與例外轉換,程式碼簡潔安全。public List getListForPage(final String hql, final Object[] params, final int offset, final int length) {
return getHibernateTemplate().executeFind(new HibernateCallback() {
public Object doInHibernate(Session session) throws HibernateException, SQLException {
Query query = session.createQuery(hql);
if (params != null) {
for (int i = 0; i < params.length; i++) {
query.setParameter(i, params[i]);
}
}
query.setFirstResult(offset);
query.setMaxResults(length);
return query.list();
}
});
}
public int getTotalCount(final String countHql) {
return ((Number) getHibernateTemplate().execute(new HibernateCallback() {
public Object doInHibernate(Session session) throws HibernateException, SQLException {
return session.createQuery(countHql).uniqueResult();
}
})).intValue();
}
靈活運用 HibernateCallback 即可在保持 Spring 事務管理優勢的同時,獲得 Hibernate 原生分頁能力,無需引入額外依賴。