Mybatis分頁外掛PageHelper的配置和使用方法
- 前言
在web開發過程中涉及到表格時,例如dataTable,就會產生分頁的需求,通常我們將分頁方式分為兩種:前端分頁和後端分頁。
前端分頁
一次性請求資料表格中的所有記錄(ajax),然後在前端快取並且計算count和分頁邏輯,一般前端元件(例如dataTable)會提供分頁動作。
特點是:簡單,很適合小規模的web平臺;當資料量大的時候會產生效能問題,在查詢和網路傳輸的時間會很長。
後端分頁
在ajax請求中指定頁碼(pageNum)和每頁的大小(pageSize),後端查詢出當頁的資料返回,前端只負責渲染。
特點是:複雜一些;效能瓶頸在MySQL的查詢效能,這個當然可以調優解決。一般來說,web開發使用的是這種方式。
我們說的也是後端分頁。
- MySQL對分頁的支援
簡單來說MySQL對分頁的支援是通過limit子句。請看下面的例子。
limit關鍵字的用法是 LIMIT [offset,] rows offset是相對於首行的偏移量(首行是0),rows是返回條數。 # 每頁10條記錄,取第一頁,返回的是前10條記錄 select * from tableA limit 0,10; # 每頁10條記錄,取第二頁,返回的是第11條記錄,到第20條記錄, select * from tableA limit 10,10;
這裡提一嘴的是,MySQL在處理分頁的時候是這樣的:
limit 1000,10 - 過濾出1010條資料,然後丟棄前1000條,保留10條。當偏移量大的時候,效能會有所下降。
limit 100000,10 - 會過濾10w+10條資料,然後丟棄前10w條。如果在分頁中發現了效能問題,可以根據這個思路調優。
- Mybatis分頁外掛PageHelper
在使用Java Spring開發的時候,Mybatis算是對資料庫操作的利器了。不過在處理分頁的時候,Mybatis並沒有什麼特別的方法,一般需要自己去寫limit子句實現,成本較高。好在有個PageHelper外掛。
1、POM依賴
Mybatis的配置就不多提了。PageHelper的依賴如下。需要新的版本可以去maven上自行選擇
1 2 3 4 5 |
|
2、Mybatis對PageHelper的配置
開啟Mybatis配置檔案,一般在Resource路徑下。我這裡叫mybatis-config.xml。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
|
這裡要注意的是PageHelper相關的配置。
如果你沒有載入Mybatis配置檔案,那麼使用的是Mybatis預設的配置。如何載入Mybatis配置檔案呢?
到你的dataSrouce配置中。
在配置sqlSessionFactory的時候,指定Mybatis核心配置檔案和mapper的路徑,程式碼如下
1 2 3 4 5 6 7 8 9 |
|
說明:
這裡配置的mapper.xml存放路徑,在Resource/mybatis-mapper資料夾下
這裡配置的mybatis-config.xml檔案,在Resource/下
3、分頁
準備一個mapper.xml,測試就隨便寫一個吧,乾脆就用工程裡的一個。
這裡這個查詢,是一個典型的多條件查詢,我們要做的是對多條件匹配到的記錄進行分頁。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
|
在Mapper.java介面中編寫對應的方法
1 |
|
先上分頁程式碼,後面再說明
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
|
說明:
1、PageHelper的優點是,分頁和Mapper.xml完全解耦。實現方式是以外掛的形式,對Mybatis執行的流程進行了強化,添加了總數count和limit查詢。屬於物理分頁。
2、Page page = PageHelper.startPage(pageNum, pageSize, true); - true表示需要統計總數,這樣會多進行一次請求select count(0); 省略掉true引數只返回分頁資料。
1)統計總數,(將SQL語句變為 select count(0) from xxx,只對簡單SQL語句其效果,複雜SQL語句需要自己寫)
Page<?> page = PageHelper.startPage(1,-1);
long count = page.getTotal();
2)分頁,pageNum - 第N頁, pageSize - 每頁M條數
A、只分頁不統計(每次只執行分頁語句)
PageHelper.startPage([pageNum],[pageSize]);
List<?> pagelist = queryForList( xxx.class, "queryAll" , param);
//pagelist就是分頁之後的結果
B、分頁並統計(每次執行2條語句,一條select count語句,一條分頁語句)適用於查詢分頁時資料發生變動,需要將實時的變動資訊反映到分頁結果上
Page<?> page = PageHelper.startPage([pageNum],[pageSize],[iscount]);
List<?> pagelist = queryForList( xxx.class , "queryAll" , param);
long count = page.getTotal();
//也可以 List<?> pagelist = page.getList(); 獲取分頁後的結果集
3)使用PageHelper查全部(不分頁)
PageHelper.startPage(1,0);
List<?> alllist = queryForList( xxx.class , "queryAll" , param);
4)PageHelper的其他API
String orderBy = PageHelper.getOrderBy(); //獲取orderBy語句
Page<?> page = PageHelper.startPage(Object params);
Page<?> page = PageHelper.startPage(int pageNum, int pageSize);
Page<?> page = PageHelper.startPage(int pageNum, int pageSize, boolean isCount);
Page<?> page = PageHelper.startPage(pageNum, pageSize, orderBy);
Page<?> page = PageHelper.startPage(pageNum, pageSize, isCount, isReasonable); //isReasonable分頁合理化,null時用預設配置
Page<?> page = PageHelper.startPage(pageNum, pageSize, isCount, isReasonable, isPageSizeZero); //isPageSizeZero是否支援PageSize為0,true且pageSize=0時返回全部結果,false時分頁,null時用預設配置
5)、預設值
//RowBounds引數offset作為PageNum使用 - 預設不使用
private boolean offsetAsPageNum = false;
//RowBounds是否進行count查詢 - 預設不查詢
private boolean rowBoundsWithCount = false;
//當設定為true的時候,如果pagesize設定為0(或RowBounds的limit=0),就不執行分頁,返回全部結果
private boolean pageSizeZero = false;
//分頁合理化
private boolean reasonable = false;
//是否支援介面引數來傳遞分頁引數,預設false
private boolean supportMethodsArguments = false;
3、有一個安全性問題,需要注意一下,不然可能導致分頁錯亂。我這裡直接貼上了這篇部落格裡的一段話。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
|