例如
從第
萬條開始取出
條記錄
代碼:
Query q = session
createQuery(
from Cat as c
);
q
setFirstResult(
);
q
setMaxResults(
);
List l = q
list();
那麼Hibernate底層如何實現分頁的呢?實際上Hibernate的查詢定義在net
sf
hibernate
loader
Loader這個類裡面
仔細閱讀該類代碼
就可以把問題徹底搞清楚
Hibernate
的Loader源代碼第
行以下
代碼:
if (useLimit) sql = dialect
getLimitString(sql);
PreparedStatement st = session
getBatcher()
prepareQueryStatement(sql
scrollable);
如果相應的數據庫定義了限定查詢記錄的sql語句
那麼直接使用特定數據庫的sql語句
然後來看net
sf
hibernate
dialect
MySQLDialect:
代碼:
public boolean supportsLimit() {
return true;
}
public String getLimitString(String sql) {
StringBuffer pagingSelect = new StringBuffer(
);
pagingSelect
append(sql);
pagingSelect
append(
limit ?
?
);
return pagingSelect
toString();
}
這是MySQL的專用分頁語句
再來看net
sf
hibernate
dialect
Oracle
Dialect:
代碼:
public boolean supportsLimit() {
return true;
}
public String getLimitString(String sql) {
StringBuffer pagingSelect = new StringBuffer(
);
pagingSelect
append(
select * from ( select row_
*
rownum rownum_
from (
);
pagingSelect
append(sql);
pagingSelect
append(
) row_ where rownum <= ?) where rownum_ > ?
);
return pagingSelect
toString();
}
Oracle采用嵌套
層的查詢語句結合rownum來實現分頁
這在Oracle上是最快的方式
如果只是一層或者兩層的查詢語句的rownum不能支持order by
除此之外
Interbase
PostgreSQL
HSQL也支持分頁的sql語句
在相應的Dialect裡面
大家自行參考
如果數據庫不支持分頁的SQL語句
那麼根據在配置文件裡面#hibernate
jdbc
use_scrollable_resultset true默認是true
如果你不指定為false
那麼Hibernate會使用JDBC
的scrollableresult來實現分頁
看Loader第
行以下
代碼:
if ( session
getFactory()
useScrollableResultSets() ) {
// we can go straight to the first required row
rs
absolute(firstRow);
}
else {
// we need to step through the rows one row at a time (slow)
for ( int m=
; m<firstRow; m++ ) rs
next();
}
如果支持scrollable result
使用ResultSet的absolute方法直接移到查詢起點
如果不支持的話
使用循環語句
rs
next一點點的移過去
可見使用Hibernate
在進行查詢分頁的操作上
是具有非常大的靈活性
Hibernate會首先嘗試用特定數據庫的分頁sql
如果沒用
再嘗試Scrollable
如果不行
最後采用rset
next()移動的辦法
在查詢分頁代碼中使用Hibernate的一大好處是
既兼顧了查詢分頁的性能
同時又保證了代碼在不同的數據庫之間的可移植性
From:http://tw.wingwit.com/Article/program/Java/ky/201311/28262.html