Java代码
Query q = session.createQuery("from Cat as c");;
q.FirstResult(20000);;
q.MaxResults(100);;
List l = q.list;;
那么Hibernate底层如何实现分页呢?实际上Hibernate查询定义在net.sf.hibernate.loader.Loader这个类里面仔细阅读该类代码就可以把问题彻底搞清楚
Hibernate2.0.3Loader源代码第480行以下:
Java代码
(useLimit); sql = dialect.getLimitString(sql);;
PreparedStatement st = session.getBatcher;.prepareQueryStatement(sql, scrollable);;
如果相应数据库定义了限定查询记录sql语句那么直接使用特定数据库sql语句
然后来看net.sf.hibernate.dialect.MySQLDialect:
Java代码
public boolean supportsLimit; {
true;
}
public String getLimitString(String sql); {
StringBuffer pagingSelect = StringBuffer(100);;
pagingSelect.append(sql);;
pagingSelect.append(" limit ?, ?");;
pagingSelect.toString;;
}
这是MySQL专用分页语句再来看net.sf.hibernate.dialect.Oracle9Dialect:
Java代码
public boolean supportsLimit; {
true;
}
public String getLimitString(String sql); {
StringBuffer pagingSelect = StringBuffer(100);;
pagingSelect.append("select * from ( select row_.*, rownum rownum_ from ( ");;
pagingSelect.append(sql);;
pagingSelect.append(" ); row_ where rownum <= ?); where rownum_ > ?");;
pagingSelect.toString;;
}
Oracle采用嵌套3层查询语句结合rownum来实现分页这在Oracle上是最快方式如果只是层或者两层查询语句rownum不能支持order by
除此的外InterbasePostgreSQLHSQL也支持分页sql语句在相应Dialect里面大家自行参考
如果数据库不支持分页SQL语句那么根据在配置文件里面 #hibernate.jdbc.use_scrollable_result true
默认是true如果你不指定为false那么Hibernate会使用JDBC2.0scrollable result来实现分页看Loader第430行以下:
Java代码
( session.getFactory;.useScrollableResultSets; ); {
// we can go straight to the first required row
rs.absolute(firstRow);;
}
{
// we need to step through the rows one row at a time (slow);
for ( m=0; m<firstRow; m ); rs.next;;
}
如果支持scrollable result使用ResultSetabsolute思路方法直接移到查询起点如果不支持话使用循环语句rs.next点点移过去
可见使用Hibernate在进行查询分页操作上是具有非常大灵活性Hibernate会首先尝试用特定数据库分页sql如果没用再尝试Scrollable如果不行最后采用r.next移动办法
在查询分页代码中使用Hibernate查询分页大好处是既兼顾了查询分页性能同时又保证了代码在区别数据库的间可移植性
最新评论