MyBatis分頁:PageHelper
📖 前言:為什么需要分頁?
在處理大量數據時,一次性從數據庫查詢并返回所有結果是不可行的,這會帶來巨大的性能和內存開銷。分頁是解決這一問題的標準方案。而PageHelper是一個極其流行的MyBatis物理分頁插件,它能以“非侵入式”的方式,讓我們無需在SQL中編寫LIMIT
子句,即可輕松實現分頁。
🎯 什么是PageHelper?
PageHelper是一個MyBatis插件,它通過AOP攔截即將執行的SQL查詢。當你發起一個分頁請求時,它會自動為你追加對應數據庫方言的分頁語句(如MySQL的LIMIT
),從而實現物理分頁。其最大的優點是你只需編寫最純粹的業務查詢SQL,將分頁邏輯與業務邏輯完全解耦。
🔧 Spring Boot集成
1. 添加依賴
在pom.xml
中引入官方的starter
依賴:
<dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper-spring-boot-starter</artifactId><version>2.1.0</version> </dependency>
2. 關于配置 (application.yml
)
在很多情況下,由于starter
強大的自動檢測能力(例如,它可以根據JDBC URL自動識別數據庫類型),PageHelper可以零配置工作,但強烈建議進行顯式配置。
為什么推薦配置?
- 穩定性:明確指定
helper-dialect
可以避免因JDBC URL不規范導致的方言識別失敗。 - 功能開啟:可以方便地開啟
reasonable
(分頁參數合理化)等高級功能。 - 清晰性:配置即文檔,讓項目配置一目了然。
推薦配置 (application.yml
)
pagehelper:helper-dialect: mysql # 明確指定數據庫方言reasonable: true # 開啟分頁參數合理化
🚀 核心用法:兩種主流風格 (Page
vs PageInfo
)
PageHelper的核心魅力在于其簡潔的調用方式。主要有兩種風格,一種是使用PageInfo
全家桶,另一種是像您展示的那樣,使用Page
對象手動封裝。
1:使用 PageInfo
(便捷的一站式方案)
這是官方最推薦的用法,它將所有分頁信息封裝在一個PageInfo
對象中,非常方便。
流程:
PageHelper.startPage(pageNum, pageSize);
List<T> list = yourMapper.select(...);
PageInfo<T> pageInfo = new PageInfo<>(list);
- 將
pageInfo
對象返回給前端。
@Service
public class UserServiceImpl implements UserService {@Autowiredprivate UserMapper userMapper;@Overridepublic PageInfo<User> findUsersByPage(int pageNum, int pageSize) {// 1. 開啟分頁PageHelper.startPage(pageNum, pageSize);// 2. 執行查詢 (這是一個普通的、不帶分頁的查詢)List<User> userList = userMapper.findAll();// 3. 將查詢結果封裝到PageInfo對象中PageInfo<User> pageInfo = new PageInfo<>(userList);return pageInfo;}
}
核心屬性與方法
PageInfo
是PageHelper返回的核心對象,它包含了豐富的分頁信息,可以直接序列化為JSON返回給前端。
屬性 | 類型 | 說明 |
---|---|---|
pageNum | int | 當前頁碼 |
pageSize | int | 每頁數量 |
size | int | 當前頁的數量 |
total | long | 總記錄數 |
pages | int | 總頁數 |
list | List<T> | 當前頁的數據列表 |
prePage | int | 上一頁頁碼 |
nextPage | int | 下一頁頁碼 |
isFirstPage | boolean | 是否為第一頁 |
isLastPage | boolean | 是否為最后一頁 |
hasPreviousPage | boolean | 是否有上一頁 |
hasNextPage | boolean | 是否有下一頁 |
優點:PageInfo
對象包含了總頁數、總條數、是否有上一頁/下一頁等所有前端分頁組件需要的信息,一步到位。
2:強轉為 Page<T>
這種方式同樣非常流行,它提供了更高的自定義靈活性。
工作原理:當PageHelper.startPage()
被調用后,PageHelper會確保緊跟其后的MyBatis查詢返回的List
對象,其實際類型是com.github.pagehelper.Page
。Page
類繼承自ArrayList
,但額外包含了分頁信息(如總條數total
)。
// 1. 開啟分頁
PageHelper.startPage(1, 10);// 2. mapper.list() 表面上返回的是 List<Emp>,
// 但其在運行時的真實類型是 Page<Emp>
List<Emp> empList = empMapper.list();// 3. 因此,可以安全地進行強制類型轉換
Page<Emp> page = (Page<Emp>) empList;
使用場景
Page<T>
主要用于需要高度自定義返回格式的場景。開發者通過將其強轉后,可以精確地提取出 total
和 list
數據,然后封裝進自己項目規定的 PageBean
或 ResultVO
等DTO(數據傳輸對象)中,完全掌控API的響應結構。
優點:返回給前端的JSON結構完全由您自己定義,可以做到最精簡,不受PageInfo
固定結構的限制。
核心屬性與方法
Page<T>
對象提供了獲取分頁所需的最基本、最核心的數據:
方法名 | 返回類型 | 說明 |
---|---|---|
getTotal() | long | 獲取總記錄數 |
getResult() | List<T> | 獲取當前頁的數據列表 (等同于對象本身) |
getPages() | int | 獲取總頁數 |
getPageNum() | int | 獲取當前頁碼 |
getPageSize() | int | 獲取每頁顯示數量 |
getStartRow() | long | 獲取當前頁的起始行號 (從1開始) |
getEndRow() | long | 獲取當前頁的結束行號 |