Spring專案處理分頁(邏輯和物理分頁)

吃肉的包子發表於2020-09-27

處理分頁問題

分頁問題總分為物理分頁和邏輯分頁兩大類。物理(SQL)分頁又有pagehelper分頁外掛、lambda函式分頁最為普遍;邏輯分頁很少使用,因為當處理資料超過10萬條以後可能會超載。


                    **老鐵們點個贊吧,給小白點鼓勵!**


前言

每次pagehelper分頁出問題,遇到苦筆的分頁問題都去百度,全都是pagehelper分頁的不同工具類的使用,最後解決問題的辦法還是依賴強大的SQL函式。


提示:以下是邏輯分頁和物理分頁的總括圖

在這裡插入圖片描述


一、物理分頁

物理分頁依賴的是某一物理實體,這個物理實體就是資料庫,比如MySQL資料庫提供了limit關鍵字,程式設計師只需要編寫帶有limit關鍵字的SQL語句,資料庫返回的就是分頁結果。

1.pagehelper分頁

  1. spring是三層架構,controller層是接收前端的持久層,分頁也一般是在這一層處理。
  2. pagehelper僅僅是對從servise層中的第一條查詢SQL返回的資料進行分頁。
  3. servise層不能改變從DAO層獲取的List長度,只能改變list中的元素

    匯入maven的pagehelper外掛為

強烈推薦閱讀——淺析pagehelper分頁原理

<dependency>
   <groupId>com.github.pagehelper</groupId>
   <artifactId>pagehelper</artifactId>
   <version>4.1.6</version>
</dependency>

controller層pagehelper應用的程式碼為

int pageNum;
int pageSize;
if (map.get("pageNum") == null || map.get("pageNum") == "") {
pageNum = 1;
} else {
pageNum = Integer.parseInt(map.get("pageNum").toString());
}
if (map.get("pageSize") == null || map.get("pageSize") == "") {
pageSize = 10;
} else {
pageSize = Integer.parseInt(map.get("pageSize").toString());
}
PageHelper.startPage(pageNum, pageSize);
List<PageData> appUserList = memberConsoleService.appUserList(map);
PageInfo<PageData> page = new PageInfo<PageData>(appUserList, pageSize);
return R.ok().put("list", appUserList).put("count", page.getTotal());

2.lambda函式分頁

lambda函式是java8才有的新特性,lambda函式與pagehelper分頁都是SQL分頁。

  1. lambda函式僅僅是對從servise層中的最後一條查詢SQL返回的資料進行分頁。
  2. servise層不能改變從DAO層獲取的List長度,只能改變list中的元素
  3. 這兩種方法都有很明顯的缺點,缺沒有辦法,害
    lambda函式在controller層的應用為
int pageIndex;
int pageSize;
if (map.get("pageSize") != null && map.get("pageNum") != null && !"".equals(map.get("pageSize"))
				&& !"".equals(map.get("pageNum"))) {
    pageIndex = Integer.parseInt(map.get("pageNum").toString());// 當前頁 前端傳
    pageSize = Integer.parseInt(map.get("pageSize").toString());// 每頁顯示條數 前端傳
		} else {
                pageIndex = 1;// 當前頁 前端傳
                pageSize = 10;// 每頁顯示條數 前端傳
		}
List<Map<String, Object>> List = firstAccountservice.querySystemAnnouncementList(map);
int total = (int) List.stream().filter(s -> !s.isEmpty()).count();// 總條數
List<Map<String, Object>> collect = List.stream().skip(pageSize * (pageIndex - 1)).limit(pageSize)
				.collect(Collectors.toList());// 資料
return R.ok().put("list", collect).put("count", total);

3.MySQL中limit函式

limit是MySQL內建函式,其作用是用於限制du查詢結果的條數。

  1. 查詢的語法:SELECT * FROM table LIMIT [offset,] rows | rows OFFSET offset
  2. select * from table limit 5; --返回前5行
  3. select * from table limit 0,5; --同上,返回前5行
  4. select * from table limit 5,10; --返回6-15行
    現在查到的limit函式的應用以及詳解都差不多,也不知道誰抄誰的,我就推薦一個你們可以去看看(主要是我也沒怎麼用)

mysql分頁——Mysql中limit的語法

二、邏輯分頁

邏輯分頁依賴的是程式設計師編寫的程式碼。資料庫返回的不是分頁結果,而是全部資料,然後再由程式設計師通過程式碼獲取分頁資料,常用的操作是一次性從資料庫中查詢出全部資料並儲存到List集合中,因為List集合有序,再根據索引獲取指定範圍的資料。

1.邏輯分頁詳解

  1. 邏輯分頁顯示從servise層獲取的全部資料放到記憶體中,然後在controller層進行分頁。
  2. 相對於物理分頁,邏輯分頁的工具包更多,我這裡有一個搜到的工具包,分享給你們看看

邏輯分頁的工具包:

package com.intelsrc.bean;

import java.util.List;
@SuppressWarnings("unchecked")
public class PageBean {
	
	private List list ;
	private int allRow;
	private int totalPage;
	public int getTotalPage() {
		return totalPage;
	}
	public void setTotalPage(int totalPage) {
		this.totalPage = totalPage;
	}
	private int currentPage;
	private int pageSize;
	
	
	private boolean isFirstPage;

	private boolean isLastPage;
	
	private boolean hasNextPage;
	
	private boolean hasPreviousPage;
	
	@SuppressWarnings("unchecked")
	public List getList() {
		return list;
	}
	@SuppressWarnings("unchecked")
	public void setList(List list) {
		this.list = list;
	}
	public int getAllRow() {
		return allRow;
	}
	public void setAllRow(int allRow) {
		this.allRow = allRow;
	}
	
	public int getCurrentPage() {
		return currentPage;
	}
	public void setCurrentPage(int currentPage) {
		this.currentPage = currentPage;
	}
	public int getPageSize() {
		return pageSize;
	}
	public void setPageSize(int pageSize) {
		this.pageSize = pageSize;
	}
	
	

	
	public void init(){
		this.isFirstPage=this.isFirstPage();
		this.isLastPage=this.isLastPage();
		this.hasNextPage=this.isHasNextPage();
		this.hasPreviousPage=this.isHasPreviousPage();
		
	}
	
	public boolean isFirstPage() {
		return currentPage==1;
	}
	public boolean isLastPage() {
		return currentPage==totalPage;
	}
	public boolean isHasNextPage() {
		return currentPage!=1;
	}
	public boolean isHasPreviousPage() {
		return currentPage!=totalPage;
	}
	/**
	 * 計算總頁數,靜態方法,供外部直接通過類名呼叫
	 * @param pageSize
	 * @param allRow
	 * @return 總頁數
	 */
	public static int countToltalPage(final int pageSize,int allRow){
		int toltalPage=allRow%pageSize==0?allRow/pageSize:allRow/pageSize+1;
		return toltalPage;
	}
	/**
	 * 計算當前頁開始記錄
	 * @param pageSize
	 * @param currentPage
	 * @return  當前頁開始記錄號
	 */
	public static int countOffset(final int pageSize,final int currentPage){
		final int offset=pageSize*(pageSize-1);
		return offset;
		
	}
	/**
	 * 計算當前頁,若為0或者請求的URL中沒有"?page=",則用1代替。
	 * @param page  page 傳入的引數(可能為空,即0,則返回1)
	 * @return 當前頁
	 */
	public static int countCurrentPage(int page){
        final int curPage = (page==0?1:page);
        return curPage;
    }

}

總結:兩種分頁的區別

分頁的引用:物理和邏輯分頁

物理分頁相比於邏輯分頁不會造成記憶體溢位,但翻頁的資料相比於邏輯分頁又慢,所以根據實際情況選擇分頁方式,如果資料量不大,可以考慮使用邏輯分頁使翻頁速度加快。。

相關文章