|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
你精通任何一门语言就最强大。现在来看,java的市场比C#大,C#容易入手,比较简单,java比较难Hibernate能够完成分页查询,比方:
从第2万条入手下手掏出100笔记录
[code:1]Queryq=session.createQuery("fromCatasc");
q.setFirstResult(20000);
q.setMaxResults(100);
Listl=q.list();[/code:1]
那末Hibernate底层怎样完成分页的呢?实践上Hibernate的查询界说在net.sf.hibernate.loader.Loader这个类内里,细心浏览该类代码,就能够把成绩完全弄分明。
Hibernate2.0.3的Loader源代码第480行以下:
[code:1]if(useLimit)sql=dialect.getLimitString(sql);
PreparedStatementst=session.getBatcher().prepareQueryStatement(sql,scrollable);[/code:1]
假如响应的数据库界说了限制查询纪录的sql语句,那末间接利用特定命据库的sql语句。
然厥后看net.sf.hibernate.dialect.MySQLDialect:
[code:1]publicbooleansupportsLimit(){
returntrue;
}
publicStringgetLimitString(Stringsql){
StringBufferpagingSelect=newStringBuffer(100);
pagingSelect.append(sql);
pagingSelect.append("limit?,?");
returnpagingSelect.toString();
}[/code:1]
这是MySQL的公用分页语句,再来看net.sf.hibernate.dialect.Oracle9Dialect:
[code:1]publicbooleansupportsLimit(){
returntrue;
}
publicStringgetLimitString(Stringsql){
StringBufferpagingSelect=newStringBuffer(100);
pagingSelect.append("select*from(selectrow_.*,rownumrownum_from(");
pagingSelect.append(sql);
pagingSelect.append(")row_whererownum<=?)whererownum_>?");
returnpagingSelect.toString();
}[/code:1]
Oracle接纳嵌套3层的查询语句分离rownum来完成分页,这在Oracle上是最快的体例,假如只是一层大概两层的查询语句的rownum不克不及撑持orderby。
除此以外,Interbase,PostgreSQL,HSQL也撑持分页的sql语句,在响应的Dialect内里,人人自行参考。
假如数据库不撑持分页的SQL语句,那末依据在设置文件内里
#hibernate.jdbc.use_scrollable_resultsettrue
默许是true,假如你不指定为false,那末Hibernate会利用JDBC2.0的scrollableresult来完成分页,看Loader第430行以下:
[code:1]if(session.getFactory().useScrollableResultSets()){
//wecangostraighttothefirstrequiredrow
rs.absolute(firstRow);
}
else{
//weneedtostepthroughtherowsonerowatatime(slow)
for(intm=0;m<firstRow;m++)rs.next();
}[/code:1]
假如撑持scrollableresult,利用ResultSet的absolute办法间接移到查询出发点,假如不撑持的话,利用轮回语句,rs.next一点点的移已往。
可见利用Hibernate,在举行查询分页的操纵上,是具有十分年夜的天真性,Hibernate会起首实验用特定命据库的分页sql,假如没用,再实验Scrollable,假如不可,最初接纳rset.next()挪动的举措。
在查询分页代码中利用Hibernate的一年夜优点是,既分身了查询分页的功能,同时又包管了代码在分歧的数据库之间的可移植性。
批评1:robbin写道
再来看net.sf.hibernate.dialect.Oracle9Dialect:
[code:1]publicbooleansupportsLimit(){
returntrue;
}
publicStringgetLimitString(Stringsql){
StringBufferpagingSelect=newStringBuffer(100);
pagingSelect.append("select*from(selectrow_.*,rownumrownum_from(");
pagingSelect.append(sql);
pagingSelect.append(")row_whererownum<=?)whererownum_>?");
returnpagingSelect.toString();
}[/code:1]
Oracle接纳嵌套3层的查询语句分离rownum来完成分页,这在Oracle上是最快的体例,假如只是一层大概两层的查询语句的rownum不克不及撑持orderby。
Oracle的这类完成假如有orderby子句仍然有成绩。某些时分会招致翻页有纪录反复大概丢失,很难找到纪律,十分奇异。
厥后往google了一下,有Oracle专家说必要orderby的时分必需带上unique的字段,比方主键大概rowid等。
别的,在利用这类接纳rownum的查询时,只管速率绝对对照快,可是背景Oracle在内存和CPU的损耗上会增添很多。实在除非了局集十分复杂(几万以上),而且必需翻倒很前面(skip的纪录良多),接纳ResultSet.absolute办法功能还能够,并没无数量级上的不同。
批评2joachimz写道
Oracle的这类完成假如有orderby子句仍然有成绩。某些时分会招致翻页有纪录反复大概丢失,很难找到纪律,十分奇异。
厥后往google了一下,有Oracle专家说必要orderby的时分必需带上unique的字段,比方主键大概rowid等。
别的,在利用这类接纳rownum的查询时,只管速率绝对对照快,可是背景Oracle在内存和CPU的损耗上会增添很多。实在除非了局集十分复杂(几万以上),而且必需翻倒很前面(skip的纪录良多),接纳ResultSet.absolute办法功能还能够,并没无数量级上的不同。
这类情形常常呈现,包含其他数据库,缘故原由就是排序中呈现不异关头字怎样处置
一个是每次分页都从头查询,也就必要从头排序
另外一个是数据库是不是实行不乱排序
起首表有个默许按次,好比主键递增,对orderby:
假如数据库接纳不乱排序,排序关头字不异时,坚持默许按次(主键递增),那末重复查询重复排序失掉的了局都是一样的
假如接纳不不乱排序,关头字不异时,按次不断定,那末重复排序时了局便可能纷歧样,因而就会呈现看似反复、漏掉的情形
举措很复杂,就是排序时加上一个主键,关于各个不不乱排序的数据库体系多数应当如许做
来自:http://www.javaeye.com/topic/261
其实产生见解的过程就是训练自己发现问题,分析问题的能力。根据以上的认识我想谈下传统的学习与通过视频独立学习的优缺点: |
|