分页查询:
在应用系统开发中,尤其是
Web
应用系统开发中,数据分页是一项普遍而又非常重要的非功能性的技术需求。因为它对于提高系统运行效率,以及减少客户端与服务器间的通信量都有着非常非常重要的作用。但是数据分页在系统实现中往往会带来很大的工作量,在基于
JDBC
的程序中,更是如此,因为不同的数据库提供了不同的数据分页技术(比如
MySQL
通过它的
Limit
字句实现数据分页,而
Oracle
通过它的
rownum
字句实现数据分页),这不但给实现带来了一定的困难,也为系统在不同数据间的移植带来了问题。
Hibernate
通过对不同的数据库提供统一的接口设计,实现了通用化透明化的数据分页机制,比如我们可以通过
QBC
查询实现数据分页。如下面代码所示:
Criteria criteria=session.createCriteria(User.class);
criteria.add(Expression.eq(“age”,20));
//
从检索结果中获取从第
100
条开始到第
120
条结束的
20
条记录
criteria.setFirstResult(100);
criteria.setFetchSize(20);
同样,在
Query
接口中也提供了与其一致的方法。
这是
Hibernate API
提供的数据分页技术,但是有时候我们需要针对某一个底层数据库,提供应用系统统一的数据分页机制。这时候我们可以通过实现
Hibernate
中的抽象类
net.sf.hibernate.dialect.
Dialect
在
Hibernate3
中为
org.hibernate.dialect.
Dialect
,这个抽象类是
Hibernate
提供的本地方言类,在本地方言类中封装了对各种不同的主流数据库特性的实现,如果需要针对某种数据库提供方言类支持,可以在
Hibernate
主配置文件中通过配置来指定(配置
hibernate.dialect
元素),通过对不同的数据库提供相应的
dialect
实现,可以消除不同数据库间的差异,从而在上层提供了一个透明的,数据库无关的存储层基础。在
Hibernate
中提供的主要
dialect
实现见下表:
Hibernate SQL
方言 (hibernate.dialect)
RDBMS
|
方言
|
DB2
|
net.sf.hibernate.dialect.DB2Dialect
|
MySQL
|
net.sf.hibernate.dialect.MySQLDialect
|
SAP DB
|
net.sf.hibernate.dialect.SAPDBDialect
|
Oracle (
所有版本)
|
net.sf.hibernate.dialect.OracleDialect
|
Oracle 9
|
net.sf.hibernate.dialect.Oracle9Dialect
|
Sybase
|
net.sf.hibernate.dialect.SybaseDialect
|
Sybase Anywhere
|
net.sf.hibernate.dialect.SybaseAnywhereDialect
|
Progress
|
net.sf.hibernate.dialect.ProgressDialect
|
Mckoi SQL
|
net.sf.hibernate.dialect.MckoiDialect
|
Interbase
|
net.sf.hibernate.dialect.InterbaseDialect
|
Pointbase
|
net.sf.hibernate.dialect.PointbaseDialect
|
PostgreSQL
|
net.sf.hibernate.dialect.PostgreSQLDialect
|
HypersonicSQL
|
net.sf.hibernate.dialect.HSQLDialect
|
Microsoft SQL Server
|
net.sf.hibernate.dialect.SybaseDialect
|
Ingres
|
net.sf.hibernate.dialect.IngresDialect
|
Informix
|
net.sf.hibernate.dialect.InformixDialect
|
FrontBase
|
net.sf.hibernate.dialect.FrontbaseDialect
|
下面我们主要看看通过
Oracle
的
dialect
实现提供的数据分页机制,对于分页机制而言,
dialect
中定义了一个方法
public String getLimitString(String sql,boolean hasoffset),
此方法用于现有的
select
语句基础上,根据各数据库自身特性,构造对应记录返回限定字句。下面是
Oracle9iDialect
中的
getLimitString
实现,在
Oracle
中实现数据分页机制是通过
Oracle
的
rownum
字句实现的数据部分提取。
public String getLimitString(String sql,boolean hasoffset){
StringBuffer pagesql=new StringBuffer(sql.length()+20);
if(hasoffset){
pagesql.append(“select * from (select row_.*,rownum rownum_ from(”);
}
else{
pagesql.append(“select * from(”);
}
pagesql.append(sql);
if(hasoffset){
pagesql.append(“) row_ where rownum<=?) where rownum_>?”);
}
else{
pagesql.append(“) where rownum<=?”);
}
return pagesql.toString();
}
这样
Hibernate
通过对底层分页机制的封装,使得开发人员无需关心数据分页机制的细节实现,在提高了生产效率的同时
,
也大大提高了数据库间的可移植性。