• 大话分页(一)


    分页是一项人性化的功能,也是查看大量显示数据的一种解决方案。然而就分页功能的实现来说,分页是多种多样的。那我们在项目中用到的时候,我该使用哪种方式进行分页呢?下面我将汇总一下分页查询的各种实现,并加以比对,当你使用时,做出较好的选择(本文讨论范畴只在真分页,下面谈到的分页也特指真分页)。


    分页共性


    凡是分页,无论使用什么方式实现,它都是以从第几条数据到第几条数据这样的思路实现的,都需要提供两个参数:

    PageNo:当前页号;

    PaseSize:每页显示的数据。


    三种数据的分页方式的比较


    MySql数据库特色分页

    最简单的方法就是利用mysql数据库的limit函数进行分页:

    limit[offset],rows可以从Mysql数据库中第M条记录开始检索N条记录的语句为:

    select * from 表名 limit M,N

    从表Sys_option(主键为sys_id)中从第10条记录开始检索20条记录,语句如下:

    select * from sys_option order by sys_id limit 10,20


    Oracle数据库常用分页

    Oracle中经常使用三层嵌套查询:

    select * from (select T.*,rownum rn from (select * from table order by id) T where rownum <PageNo*PageSize) where rn >=(PageNo-1)*PageSize

    PageNo为当前页数;

    PageSize为每页显示数据数目。

    查询的是从第(PageNo-1)*PageSize条数据到第PageNo*PageSize条数据。


    例子:从t_student表中取出第20到40条数据

    select * from (select A.*,rownum rn from (select * from t_student order by id) A where rownum <41) where rn >=20


    问为什么Oracle要使用三层嵌套查询实现分页呢?

    其实这跟Oracle数据库的特性有关,rownum的赋值默认从1开始。如果不适用嵌套查询,我们会写出下面的语句:

    select rownum,id from (select * from t_student order by id) where rownum >=m and rownum < n; 

    当执行 rownum>m 且 m>1 时,由于rownum默认为1,这也就是一个不成立的条件,所以会查不出数据,所以采用三层嵌套语句,将rownum变成一个临时表的字段,这时候就没有oracle数据特性的限制了。


    SqlServer数据常用分页

    查询第一页的五条数据比较好查询,那么怎样查询第二页的数据呢(也就是第6到第10条记录)?

    第二页的记录就是紧跟这第一页显示的记录之后的5条记录,也就是通过对userID字段进行降序排列时,它们是除了第一页数据之后的5条记录,也就是它们的userID不在第一页的UserID之中,在SQL语句有一个not in这个正好可以排上用场。 首先我们按照对UserID进行降序排序,查询出前面第一页使用的数据的UserID,SQL语句及执行结果如下:

    select top 5 * from t_User where userID not in (select 5 userID from t_User order by userID asc) order by userID asc


    userID是从1开始,所以userID在1至5的记录在第一页显示,userID为6至10的记录在第二页显示,userID为11至15的记录在第三页显示……依此类推,如果每页显示5条记录,那么第n页显示的数据记录的公式应该是:

    select top 5 * from t_User where userID not in (select top(n-1)*5 userID from t_User order by userID asc) order by userID asc


    Hibernate框架的分页

    根据上面我们可以看出:每种数据都有自己特色的内容可以完成分页功能。Hibernate框架再此基础上进行封装,只需要Query接口中setMaxResultsset和FirstResult方法即可完成分页。采用Hibernate的好处就是:如果你使用的mysql数据库,那么Hibernate就会按照Mysql的规则生成相应的分页语句;如果使用Oracle数据库,那么它也会相应的生成对应的Oracle分页语句。也就是说,Hibernate框架实现分页,与具体数据库是无关的,有利于更换数据库。

    下面看一个Hibernate实现分页的工具类的主要方法:

    public class AbstractPageManager extends HibernateDaoSupport {
    
    	/**
    	 * 根据HQL语句,获得查找总记录数的HQL语句 如: 
    	 * select ... from Organization o where o.parent is null 
    	 * 经过转换,可以得到: 
    	 * select count(*) from Organization o where o.parent is null
    	 * 
    	 * @param hql
    	 * @return
    	 */
    	private String getCountQuery(String hql) {
    		// 取得from的位置
    		int index = hql.indexOf("from");
    
    		// 返回:查询记录条数 的SQL语句
    		if (index != -1) {
    			return "select count(*) " + hql.substring(index);
    		}
    		throw new SystemException("无效的HQL查询语句");
    	}
    	
    	/**
    	 * 根据HQL语句进行分页查询
    	 * 
    	 * @param hql HQL语句
    	 * @param params HQL语句带的多个参数
    	 * @param offSet 从第几个记录开始查询
    	 * @param pageSize 每页显示多少行
    	 * @return
    	 */
    	public PageModel searchPaginate(String hql, Object[] params, int offSet,
    			int pageSize) {
    		// 记录条数
    		String strCount = getCountQuery(hql);
    
    		// 查询条数
    		Query query = getSession().createQuery(strCount);
    		// 将HQL语句带的多个参数 赋值给Query
    		if (params != null && params.length > 0) {
    			for (int i = 0; i < params.length; i++) {
    				query.setParameter(i, params[i]);
    			}
    		}
    
    		// 获取查询条数
    		int intCount = ((Long) query.uniqueResult()).intValue();
    
    		// 查询Organization记录
    		query = getSession().createQuery(hql);
    		// 将HQL语句带的多个参数 赋值给Query
    		if (params != null && params.length > 0) {
    			for (int i = 0; i < params.length; i++) {
    				query.setParameter(i, params[i]);
    			}
    		}
    		/*
    		 * offSet 设置从第几个记录开始查询
    		 * pageSize 设置每页显示多少行
    		 */
    		query.setFirstResult(offSet);
    		query.setMaxResults(pageSize);
    
    		//组装PageModel
    		PageModel pageModel = new PageModel();
    		pageModel.setDatas(query.list());
    		pageModel.setTotal(intCount);
    		
    		return pageModel;
    	}
    }


    由上可知:MySql、Oracle和SqlServer三种数据库有通性的地方,同时也有自己特色的内容。如果使用数据库特色的语句,是不利于数据库的移植的。Hibernate框架在此基础上进行封装,只需要通过setMaxResultsset()和FirstResult()方法设置offSet和pageSize,就能根据数据库生成特色语句,具体实现有兴趣的同学可以自行研究Hibernate源码,我这里就不往上贴了。

    未完待续。。


  • 相关阅读:
    Django的是如何工作的
    Robot Framework自动化测试(五)--- 开发系统关键字
    Swarm 如何存储数据?- 每天5分钟玩转 Docker 容器技术(103)
    如何滚动更新 Service?- 每天5分钟玩转 Docker 容器技术(102)
    Service 之间如何通信?- 每天5分钟玩转 Docker 容器技术(101)
    神奇的 routing mesh
    如何访问 Service?- 每天5分钟玩转 Docker 容器技术(99)
    Swarm 如何实现 Failover?- 每天5分钟玩转 Docker 容器技术(98)
    如何实现 Service 伸缩?- 每天5分钟玩转 Docker 容器技术(97)
    运行第一个 Service
  • 原文地址:https://www.cnblogs.com/pangblog/p/3339414.html
Copyright © 2020-2023  润新知