hibernte分页

    技术2022-05-11  31

    hibernate中通过对不同数据库中统一接口设计,实现了透明化,通用化的分页实现机制。通过针对不同的dialect(数据库方言),来实现hibernate高度的可移植性。

    可以通过Criteria.setFirstResult和Criteria.setFetchSize方法设定分页范围

    eg.

    Criteria criteria = session.createCriteria(TUser.class);criteria.add(Expression.eq("age","20"));//从检索结果中获取第100条记录开始的20条记录criteria.setFirstResult(100);criteria.setFetchSize(20);

    Hibernate中,抽象类net.sf.hibernate.dialect指定了所有底层数据库的对外统一接口。通过针对不同数据库提供相应的dialect实现,数据库之间的差异性得以消除,从而为上层机制提供了透明的、数据库无关的存储层基础。

    对于分页机制而言, dialect中定义了一个getLimitString方法,此方法用于在现有Select 语句基础上,根据各数据库自身特性,构造对应的记录返回限定子句。如MySQL中对应的记录限定子句为Limit,而Oracle中,可通过rownum子句实现。

    我们来看MySQLDialect中的getLimitString实现:

    public String getLimitString(String sql, boolean hasOffset) {return new StringBuffer( sql.length()+20 ).append(sql).append( hasOffset ? " limit ?, ?" : " limit ?").toString();}

    从上面可以看到,MySQLDialect.getLimitString方法的实现实际上是在给定的Select语句后追加MySQL所提供的专有SQL子句limit来实现。

    通过Oracle 特有的rownum子句可以实现了数据的部分读取:

    public String getLimitString(String sql, boolean hasOffset){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 <= ?) where rownum_ > ?");}else {pagingSelect.append(" ) where rownum <= ?");}return pagingSelect.toString();}

    大多数主流数据库都提供了数据部分读取机制,而对于某些没有提供相应机制的数据库而言,Hibernate也通过其他途径实现了分页,如通过Scrollable ResultSet,如果JDBC 不支持Scrollable ResultSet,Hibernate 也会自动通过ResultSet 的next 方法进行记录定位。这样,Hibernate 通过底层对分页机制的良好封装,使得开发人员无需关心数据分页的细节实现,将数据逻辑和存储逻辑分离开来,在提高生产效率的同时,也大大加强了系统在不同数据库平台之间的可移植性。

    简单举例:

    Query query = _session.createQuery(hql.toString());

    query.setMaxResults(limit).setFirstResult(row).list();

    这是常用的方法。

    资料:Hibernate 开发指南 


    最新回复(0)