在企業級應用開發中,依據時間區間篩選資料是極為常見的需求。本文將透過實際代碼示範,說明如何在 Hibernate 中運用 HQL(Hibernate Query Language)與 QBC(Query By Criteria)兩種主流查詢方式,高效完成日期範圍的資料檢索。
資料庫對日期時間的儲存格式各有差異(如 Oracle 的 DATE、MySQL 的 DATETIME、SQL Server 的 DATETIME2 等)。為了確保跨資料庫的相容性,團隊討論後傾向於採用字串格式統一儲存,或在應用層統一轉換為 java.sql.Date / java.sql.Timestamp 再持久化,避免因資料庫遷移導致的查詢邏輯錯誤。
HQL 寫法直觀,贴近 SQL 語法,支援命名參數,能有效防止 SQL 注入。以下示範查詢 2009-03-24 至 2009-03-26 之間的記錄:
Session session = HibernateSessionFactory.getSession();
Transaction tx = session.beginTransaction();
Date begin = java.sql.Date.valueOf("2009-03-24");
Date end = java.sql.Date.valueOf("2009-03-26");
String hql = "from A a where a.date > :beginTime and a.date <= :endTime";
List<A> result = session.createQuery(hql)
.setTimestamp("beginTime", begin)
.setTimestamp("endTime", end)
.list();
for (A a : result) {
System.out.println(a.getId());
System.out.println(a.getTitle());
System.out.println(a.getDate());
}
tx.commit();
session.close();
關鍵點:使用 setTimestamp 而非 setDate,可保留時分秒精度,避免邊界條件遺漏資料。
Criteria API 以物件導向方式建構查詢,適合動態條件組合,程式碼更具型別安全與重構友善性:
Session session = HibernateSessionFactory.getSession();
Transaction tx = session.beginTransaction();
Date begin = java.sql.Date.valueOf("2009-03-24");
Date end = java.sql.Date.valueOf("2009-03-26");
Criteria criteria = session.createCriteria(AbstractA.class);
Criterion criterion = Restrictions.between("date", begin, end); // 包含邊界
List<A> result = criteria.add(criterion).list();
for (A a : result) {
System.out.println(a.getId());
System.out.println(a.getTitle());
System.out.println(a.getDate());
}
tx.commit();
session.close();
注意:Hibernate 5.2 起 Expression 已棄用,建議改用 org.hibernate.criterion.Restrictions。
setFirstResult/setMaxResults 避免記憶體溢位。