`HibernateTemplate` 是 Spring 早期提供的 Hibernate 存取模板類,封裝了 Session 管理、異常轉換、資源釋放等樣板代碼。雖然 Spring 3.0+ 推薦直接使用 `SessionFactory.getCurrentSession()` 配合 `@Transactional`,但大量存量專案仍在使用 `HibernateTemplate`。本文針對其兩大常見操作——批量刪除與分頁查詢——提供最佳實踐範例。
public int delNews(final List<Long> arrId) {
return ((Integer) getHibernateTemplate().execute(
new HibernateCallback<Integer>() {
@Override
public Integer doInHibernate(Session session) throws HibernateException, SQLException {
Query query = session.createQuery(
"DELETE FROM News WHERE arrid IN (:ids)"
);
query.setParameterList("ids", arrId);
return query.executeUpdate();
}
}
)).intValue();
}
public int batchDelete(List<Long> ids, int batchSize) {
if (ids == null || ids.isEmpty()) return 0;
int totalDeleted = 0;
for (int i = 0; i < ids.size(); i += batchSize) {
List<Long> batch = ids.subList(i, Math.min(i + batchSize, ids.size()));
totalDeleted += deleteBatch(batch);
}
return totalDeleted;
}
private int deleteBatch(List<Long> batch) {
return ((Integer) getHibernateTemplate().execute(
new HibernateCallback<Integer>() {
@Override
public Integer doInHibernate(Session session) {
Query q = session.createQuery("DELETE FROM News WHERE arrid IN (:ids)");
q.setParameterList("ids", batch);
return q.executeUpdate();
}
}
)).intValue();
}
public List<News> getNewsList(final int pageSize) {
return (List<News>) getHibernateTemplate().execute(
new HibernateCallback<List<News>>() {
@Override
public List<News> doInHibernate(Session session) throws HibernateException, SQLException {
String hql = "FROM News n ORDER BY n.id DESC";
Query query = session.createQuery(hql);
query.setMaxResults(pageSize); // 限制回傳筆數
List<News> list = query.list();
return (list != null && !list.isEmpty()) ? list : null;
}
}
);
}
public List<News> getNewsPage(final int pageNo, final int pageSize) {
return (List<News>) getHibernateTemplate().execute(
new HibernateCallback<List<News>>() {
@Override
public List<News> doInHibernate(Session session) {
Query query = session.createQuery("FROM News n ORDER BY n.id DESC");
query.setFirstResult((pageNo - 1) * pageSize); // 起始位移 (0-based)
query.setMaxResults(pageSize); // 每頁筆數
return query.list();
}
}
);
}
public long getNewsCount() {
return ((Long) getHibernateTemplate().execute(
new HibernateCallback<Long>() {
@Override
public Long doInHibernate(Session session) {
return (Long) session.createQuery("SELECT COUNT(*) FROM News").uniqueResult();
}
}
)).longValue();
}
public interface NewsRepository extends JpaRepository<News, Long> {
// 方法名自動生成查詢
List<News> findTop10ByOrderByIdDesc(); // 等同 setMaxResults(10)
// 分頁查詢
Page<News> findAllByOrderByIdDesc(Pageable pageable);
// 批量刪除
@Modifying
@Query("DELETE FROM News n WHERE n.arrid IN :ids")
int deleteByArrIdIn(@Param("ids") List<Long> ids);
}
@Repository
public class NewsDao {
@Autowired private SessionFactory sessionFactory;
public int deleteByIds(List<Long> ids) {
Session session = sessionFactory.getCurrentSession();
Query query = session.createQuery("DELETE FROM News WHERE arrid IN (:ids)");
query.setParameterList("ids", ids);
return query.executeUpdate();
}
public List<News> findLatest(int limit) {
Session session = sessionFactory.getCurrentSession();
Query query = session.createQuery("FROM News n ORDER BY n.id DESC");
query.setMaxResults(limit);
return query.list();
}
}
`HibernateTemplate` 時代的批量刪除與分頁查詢核心在於: