分页查询就是这样

一、   分页查询简介

       首先,在很多地方都可以用到分页查询,软件开发最基本的增、删、改、查里面的“查”,查询所有用户需要分页,查询相关业务信息需要分页。

分页查询分为下面两种方式:

1.1、     逻辑分页

在sql查询时,先从数据库检索出所有数据的结果集,然后在程序内,通过逻辑语句获得分页需要的的数据。

例如: 检索11-20条userList.subList(10,20);

1.2、     物理分页

在sql查询时,从数据库只检索分页需要的数据。通常不同的数据库有着不同的物理分页语句,mysql物理分页,采用limit关键字。

例如:检索11-20条 select *from user limit 10,10 ;(limit m,n 是mysql的语法)

下面介绍的分页查询就是以mysql为例进行说明的。

1.3、     sql语句的分页解析

select * from tablelimit m,n; 其中m是指记录开始的index(从0开始表示第一条记录),n是指从第m+1条开始,取n条。

好了,这是mysql数据库中sql语句的分页原理。下面看具体实施。

二、   分页查询方案

2.1、  不用分页获取集合信息

在这里我用的是最基础的servlet来实现控制层与视图层进行交互,在各大框架中原理也是类似,更简单。

       我们现在要做一个客户管理系统,前端页面需要返回客户基本信息。比如:


假设我们现在不用分页的话,在后台控制器里面我们需要返回一个List

List list =custService.findAll       ();

request.setAttribute("list", list);

request.getRequestDispatcher("/list.jsp").forward(request,response);

我们只需要给页面返回一个Cust实体类的集合list,然后在页面进行遍历就可以拿到所有的客户信息。这样的话只有一个Cust实体类已经足够,因为我们要的仅仅只是Cust的一个集合。

然后业务层,DAO层你只需稍微处理一下就可以了,比如DAO层的SQL应该只需这样写就可以了:"select * fromcustomer ";

2.1、  分页获取集合信息

好了,因为客户信息太多了(几百条、几万条甚至更多),我们又不想用逻辑分页,我们应该做一下几个步骤。

2.2.1、      针对控制层:

l  第一步,你要从前端获取当前需要显示的页(第几页)和每页的记录数。

l  第二步,调用业务层(service)中分页查询的方法。

l  第三步,存入request带到前端页面(jsp)。

代码如下所示:

                //1、获取当前要显示的页和每页记录数
		int thisPage = Integer.parseInt(request.getParameter("thisPage"));
		int pageSize = Integer.parseInt(request.getParameter("pageSize"));
		//2、调用service中分页查询客户的方法
		List list = custService.findCustPage(thisPage, pageSize);
####首先,说明一点,这里只返回一个Cust的List是不够的,先放在这里,等下再修改这里的代码,这样更易于理解###
		//3、存入request带到我们的jsp页面中
		request.setAttribute("list", list);
request.getRequestDispatcher("/pageList.jsp").forward(request, response);

*思考问题*

接下来,我们思考一个问题,我们首页需要显示数据的详细信息之外(也就是一个实体类的集合需要展示在页面上的信息),还需要显示什么信息呢?我们是不是还需要显示下面这个:

XXX条记录XX首页上一页 1 2 3 4 5 下一页尾页

那我们后端控制层只返回一个Cust的List够不够?显然是不够的,这样我们在service层分页查询客户信息方法处理的时候就需要注意了:

我们是不是需要bean类来封装一些信息,以便于放入request域在前端显示,比如:bean里卖年封装一个List、当前页码thisPage、每页大小pageSize、总记录数allRow等等。那么这个bean如下所示:

2.2.2、      针对工具bean

因为现在只处理一个实体类Cust,这个bean没有用泛型写成通用的bean,应该是要写成通用的pageBean的,不过在这里为了方便讲清楚分页的原理暂时不涉及泛型:

import java.util.List;

public class CustPage {
	
	/**
	 * 当前页码
	 */
	private int thisPage;
	/**
	 * 每页大小
	 */
	private int pageSize;
	/**
	 * 总记录数
	 */
	private long allRow; 
	/**
	 * 总页
	 */
	private int totalPage;
	/**
	 * 首页
	 */
	private int firstPage;
	/**
	 * 尾页
	 */
	private int lastPage;
	/**
	 * 上一页
	 */
	private int previousPage;
	/**
	 * 下一页
	 */
	private int nextPage;
	/**
	 * 返回的Custs列表
	 */
	private List list;
	
	public CustPage() {
	}
	public CustPage(int thisPage, int pageSize, long allRow, int totalPage, int firstPage, int lastPage,
			int previousPage, int nextPage, List list) {
		super();
		this.thisPage = thisPage;
		this.pageSize = pageSize;
		this.allRow = allRow;
		this.totalPage = totalPage;
		this.firstPage = firstPage;
		this.lastPage = lastPage;
		this.previousPage = previousPage;
		this.nextPage = nextPage;
		this.list = list;
	}
	public int getThisPage() {
		return thisPage;
	}
	public void setThisPage(int thisPage) {
		this.thisPage = thisPage;
	}
	public int getPageSize() {
		return pageSize;
	}
	public void setPageSize(int pageSize) {
		this.pageSize = pageSize;
	}
	public long getAllRow() {
		return allRow;
	}
	public void setAllRow(long allRow) {
		this.allRow = allRow;
	}
	public int getTotalPage() {
		return totalPage;
	}
	public void setTotalPage(int totalPage) {
		this.totalPage = totalPage;
	}
	public int getFirstPage() {
		return firstPage;
	}
	public void setFirstPage(int firstPage) {
		this.firstPage = firstPage;
	}
	public int getLastPage() {
		return lastPage;
	}
	public void setLastPage(int lastPage) {
		this.lastPage = lastPage;
	}
	public int getPreviousPage() {
		return previousPage;
	}
	public void setPreviousPage(int previousPage) {
		this.previousPage = previousPage;
	}
	public int getNextPage() {
		return nextPage;
	}
	public void setNextPage(int nextPage) {
		this.nextPage = nextPage;
	}
	public List getList() {
		return list;
	}
	public void setList(List list) {
		this.list = list;
	}
}

2.2.3、      针对业务层

我们需要在业务层处理所有的业务,将上面CustPage这个bean里面我们需要在前端显示的信息装进去。代码如下:

        @Override
	public CustPage findCustPage(int thisPage, int pageSize) {
		
		CustPage custPage = new CustPage();
		
		//设置当前页
		custPage.setThisPage(thisPage);
		//设置每页大小
		custPage.setPageSize(pageSize);
		//查找总记录数,设置总记录数
		long allRow = custDao.getAllRow();
		custPage.setAllRow(allRow);
		//计算总页数并设置
		int totalPage = (int) (allRow/pageSize+(allRow%pageSize==0?0:1));
		custPage.setTotalPage(totalPage);
		//设置首页
		custPage.setFirstPage(1);
		//设置尾页
		custPage.setLastPage(totalPage);
		//设置上一个
		custPage.setPreviousPage(thisPage==1?1:thisPage-1);
		//设置下一页
		custPage.setNextPage(thisPage==totalPage?totalPage:thisPage+1);
		//获得需要分页的实体类数据
		List list = custDao.getCustByPage((thisPage-1)*pageSize,pageSize);
		custPage.setList(list);
		
		return custPage;
	}

2.2.4、      针对DAO层

我在这里使用了阿帕奇的一个jdbc工具,DBUtils。是一个非常轻量,非常好用的DAO层JDBC工具,现在的Hibernate太庞大了。有兴趣的朋友可以查看我其他博文进行了解。


        @Override
	public long getAllRow() {
		String sql = "select count(*) from customer";
		try{
			QueryRunner runner = new QueryRunner(DataSourceUtils.getDataSource());
			return (Long)runner.query(sql, new ScalarHandler());
		}catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException();
		}
	}
	@Override
	public List getCustByPage(int thisPage, int pageSize) {
		String sql = "select * from customer limit ?,?";
		try{
			QueryRunner runner = new QueryRunner(DataSourceUtils.getDataSource());
			return runner.query(sql, new BeanListHandler(Cust.class), thisPage,pageSize);
		}catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException();
		}
	}

好了,到这里,大概已经清楚了分页的原理,具体运用到项目中,还是需要自己实践。


你可能感兴趣的:(卡罗之web常用)