Query q = session.createQuery("from Cat");
q.setFirstResult(20000); // 從第 20001 條開始
q.setMaxResults(100); // 取 100 條
List list = q.list();
if (useLimit) {
sql = dialect.getLimitString(sql); // 方言專用分頁 SQL
}
PreparedStatement st = session.getBatcher().prepareQueryStatement(sql, scrollable);
public String getLimitString(String sql) {
return new StringBuffer(sql).append(" limit ?, ?").toString();
}
// 生成: SELECT * FROM cat LIMIT 20000, 100
public String getLimitString(String sql) {
StringBuffer pagingSelect = new StringBuffer(100);
pagingSelect.append("select * from (select row_.*, rownum rownum_ from (");
pagingSelect.append(sql);
pagingSelect.append(") row_ where rownum <= ?) where rownum_ > ?");
return pagingSelect.toString();
}
// 生成:
// SELECT * FROM (
// SELECT row_.*, ROWNUM rownum_ FROM (
// SELECT * FROM cat
// ) row_ WHERE ROWNUM <= 20100
// ) WHERE rownum_ > 20000
原因:單層 ROWNUM 不支持 ORDER BY,三層嵌套是 Oracle 最快分頁方案。
LIMIT ? OFFSET ?LIMIT ? OFFSET ?ROWS ? TO ?OFFSET ? ROWS FETCH NEXT ? ROWS ONLYDialect.supportsLimit()=true 的數據庫原生分頁if (session.getFactory().useScrollableResultSets()) {
rs.absolute(firstRow); // 直接定位
} else {
for (int m=0; m
# hibernate.cfg.xml
<property name="hibernate.jdbc.use_scrollable_resultset">true</property>