分頁查詢就是這樣

一、   分頁查詢簡介

       首先,在很多地方都可以用到分頁查詢,軟件開發最基本的增、刪、改、查裏面的“查”,查詢所有用戶需要分頁,查詢相關業務信息需要分頁。

分頁查詢分爲下面兩種方式:

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<Cust>:

List<Cust> 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<Cust> 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<Cust>、當前頁碼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<Cust> list;
	
	public CustPage() {
	}
	public CustPage(int thisPage, int pageSize, long allRow, int totalPage, int firstPage, int lastPage,
			int previousPage, int nextPage, List<Cust> 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<Cust> getList() {
		return list;
	}
	public void setList(List<Cust> 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<Cust> 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<Cust> 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>(Cust.class), thisPage,pageSize);
		}catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException();
		}
	}

好了,到這裏,大概已經清楚了分頁的原理,具體運用到項目中,還是需要自己實踐。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章