“hibernate是真分页么?我今天看了一些帖子,好像是真分页。……”
这个问题不能简单地用“真”或“假”来回答。Hibernate分页的“真”与“假”,取决于所指定的方言(Dialect)。分析了一下Hibernate中相关的源代码,目前的结论是:OracleDialect、Oracle9Dialect、MySQLDialect、MySQL5Dialect是真分页,SQLServerDialect是假分页。
题外话:对于SQLServer下的分页,我以前为学员们写过一个分页组件,是专门针对于SQLServer的,真分页,使用简单,并提供了缓存机制。
两段简单的测试代码:
1、假设我想查询第1到第10条记录
public static void main(String[] args) {
int offset = 0; //可以理解为起始行号
int limit = 10; //可以理解为每页的最大记录数
String sql = "select * from MyTable"; //原始SQL语句
Dialect dialect = null;
//测试Oracle9方言的分页功能
dialect = new Oracle9Dialect();
System.out.println( "Oracle9方言生成的SQL分页语句:" );
System.out.println( dialect.getLimitString( sql, offset, limit ) );
//测试MySQL的分页功能
dialect = new MySQLDialect();
System.out.println( "MySQL方言生成的SQL分页语句:" );
System.out.println( dialect.getLimitString( sql, offset, limit ) );
//测试SQLServer的分页功能
dialect = new SQLServerDialect();
System.out.println( "SQLServer方言生成的SQL分页语句:" );
System.out.println( dialect.getLimitString( sql, offset, limit ) );
}
以下是控制台输出:
Oracle9方言生成的SQL分页语句: select * from ( select * from MyTable ) where rownum <= ? MySQL方言生成的SQL分页语句: select * from MyTable limit ? SQLServer方言生成的SQL分页语句: select top 10 * from MyTable
2、现在我想改查第11到第20条记录
public static void main(String[] args) {
//现在我想查询第11到20条记录
int offset = 10; //可以理解为起始行号
int limit = 10; //可以理解为每页的最大记录数
String sql = "select * from MyTable"; //原始SQL语句
Dialect dialect = null;
//测试Oracle9方言的分页功能
dialect = new Oracle9Dialect();
System.out.println( "Oracle9方言生成的SQL分页语句:" );
System.out.println( dialect.getLimitString( sql, offset, limit ) );
//测试MySQL的分页功能
dialect = new MySQLDialect();
System.out.println( "MySQL方言生成的SQL分页语句:" );
System.out.println( dialect.getLimitString( sql, offset, limit ) );
//测试SQLServer的分页功能
dialect = new SQLServerDialect();
System.out.println( "SQLServer方言生成的SQL分页语句:" );
System.out.println( dialect.getLimitString( sql, offset, limit ) );
}
以下是控制台输出:
Oracle9方言生成的SQL分页语句: select * from ( select row_.*, rownum rownum_ from ( select * from MyTable ) row_ where rownum <= ?) where rownum_ > ? MySQL方言生成的SQL分页语句: select * from MyTable limit ?, ? SQLServer方言生成的SQL分页语句: Exception in thread "main" java.lang.UnsupportedOperationException: sql server has no offset at org.hibernate.dialect.SQLServerDialect.getLimitString(SQLServerDialect.java:53) at test.Test.main(Test.java:30)
上述结果是如何产生的呢?让我们来查看一下Hibernate中相关的源代码:
1、Oracle9Dialect.java(OracleDialect.java中的代码与此类似)
public String getLimitString(String sql, boolean hasOffset) {
sql = sql.trim();
boolean isForUpdate = false;
if ( sql.toLowerCase().endsWith(" for update") ) {
sql = sql.substring( 0, sql.length()-11 );
isForUpdate = true;
}
StringBuffer pagingSelect = new StringBuffer( sql.length()+100 );
if (hasOffset) {
pagingSelect.append("select * from ( select row_.*, rownum rownum_ from ( ");
}
else {
pagingSelect.append("select * from ( ");
}
pagingSelect.append(sql);
if (hasOffset) {
pagingSelect.append(" ) row_ ) where rownum_ <= ? and rownum_ > ?");
}
else {
pagingSelect.append(" ) where rownum <= ?");
}
if ( isForUpdate ) {
pagingSelect.append( " for update" );
}
return pagingSelect.toString();
}
2、MySQLDialect.java(MySQL5Dialect.java)
public String getLimitString(String sql, boolean hasOffset) {
return new StringBuffer( sql.length()+20 )
.append(sql)
.append( hasOffset ? " limit ?, ?" : " limit ?")
.toString();
}
3、SQLServerDialect.java
public String getLimitString(String querySelect, int offset, int limit) {
//以下这句就是第2段测试代码出异常的原因了,呵呵。由此可知,对于SQLServer的分页,Hibernate中对于SQLServer的分页,只会使用一次top子句取出前面的部分记录,来通过操作游标来获取指定页的数据,是假分页。
if ( offset > 0 ) {
throw new UnsupportedOperationException( "sql server has no offset" );
}
return new StringBuffer( querySelect.length()+8 )
.append(querySelect)
.insert( getAfterSelectInsertPoint(querySelect), " top " + limit )
.toString();
}
SQLServerDialect没有重写public String getLimitString(String sql, boolean hasOffset)方法,以下是该方法在其父类Dialect的实现。
public String getLimitString(String querySelect, boolean hasOffset) {
throw new UnsupportedOperationException( "paged queries not supported" );
}
public String getLimitString(String querySelect, int offset, int limit) {
return getLimitString( querySelect, offset>0 );
}
分享到:
相关推荐
NULL 博文链接:https://hgflybird.iteye.com/blog/374872
《计算机技术在计算机应用技术中的应用浅论》 要求: 结合自己所学专业命题,如"计算机技术在医学中的应用浅论"、"计算机技术在电子商务 中的应用浅论"、"计算机技术在教学管理中的应用浅论"……,阐述计算机技术在...
浅论MATLAB的特定人语音识别软件开发与设计.docx浅论MATLAB的特定人语音识别软件开发与设计.docx浅论MATLAB的特定人语音识别软件开发与设计.docx浅论MATLAB的特定人语音识别软件开发与设计.docx浅论MATLAB的特定人...
浅论洛克的自由与法治思想.docx
建筑行业是一个资源和能源消耗高,环境污染重的行业,而以牺牲环境、生态和可持续发展为代价的传统建筑逐渐被淘汰,"绿色建筑"从最初简单的概念...设计项目是否真的"绿色",这是建设、施工、设计各方应该共同重视的问题。
浅论洛克的自由与法治思想.pdf
浅论企业营销DNA与模仿营销.doc
浅论工程质量控制与验收余飞.doc
浅论建设工程招标与招投标.doc
浅论高等教育法规与合格的高校教师
浅论多媒体教育技术与网络通信技术的结合与创新.pdf
浅论企业信息化与流程的关系.docx
浅论证券交易所与证券市场监管.docx
浅论会计信息化与ERP之间的关系
浅论未来船舶电力系统智能化的发展与实现.pdf
浅论审计风险因素与信息化审计策略.docx
浅论中学语文教学与创新能力的培养.pdf
浅论中学语文教学与创新能力的培养.docx