PageHelper
是一個優秀的 MyBatis 分頁插件,它通過簡單的攔截器機制,實現了對 MyBatis 查詢的物理分頁(而非內存分頁),極大簡化了分頁代碼的編寫。而 PageHelper 擴展 通常指的是在其核心功能基礎上,為特定框架(如 Spring Boot)或特定需求(如簡化配置、增強功能)提供的增強模塊或使用方式。
以下是對 PageHelper
及其常見擴展的介紹:
一、核心 PageHelper 功能回顧
- 核心原理:
- 基于 MyBatis 的
Interceptor
接口,攔截 Executor 的查詢方法。 - 在執行目標 SQL 前,自動分析原 SQL 并生成
COUNT
查詢(獲取總數)和添加了物理分頁(如LIMIT
,ROWNUM
)的查詢。
- 基于 MyBatis 的
- 基本用法:
// 在查詢方法前調用,設置分頁參數 PageHelper.startPage(pageNum, pageSize); // pageNum: 頁碼, pageSize: 每頁條數 // 緊接著的第一個 MyBatis 查詢方法會被分頁 List<Country> list = countryMapper.selectAll(); // 用 PageInfo 包裝結果,包含分頁詳細信息(總記錄數、總頁數、當前頁等) PageInfo<Country> pageInfo = new PageInfo<>(list);
- 主要優點:
- 簡單:一行代碼啟動分頁。
- 高效:物理分頁,數據庫壓力小。
- 通用:支持多種數據庫(MySQL, Oracle, PostgreSQL, SQLServer 等)。
- 靈活:支持多種參數傳遞方式(
startPage
方法、RowBounds
參數)。 - 豐富信息:
PageInfo
對象提供全面的分頁信息。
二、重要的 PageHelper 擴展
-
pagehelper-spring-boot-starter
- 定位:官方提供的 Spring Boot 自動配置 Starter。
- 核心價值:
- 零配置/簡化配置:只需引入依賴,大部分情況下無需任何額外配置即可使用。
- 自動注入:自動配置
PageHelper
攔截器并將其注冊到 MyBatisSqlSessionFactory
中。 - 約定優于配置:遵循 Spring Boot 的配置習慣,可以通過
application.properties
/application.yml
輕松配置插件屬性。
- 依賴 (Maven):
<dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper-spring-boot-starter</artifactId><version>最新版本</version> <!-- 請替換為當前最新版本,如 2.1.0 --> </dependency>
- 常用配置示例 (
application.yml
):pagehelper:helper-dialect: mysql # 指定數據庫方言(通常可自動檢測)reasonable: true # 啟用合理化:pageNum<=0 時設為 1,pageNum>總頁數時設為最后一頁support-methods-arguments: true # 支持通過 Mapper 接口參數傳遞分頁參數params: count=countSql # 配置 COUNT 查詢的返回值 keypage-size-zero: true # 允許 pageSize=0 時查詢所有結果(返回 PageInfo,total=實際條數)
- 使用:在 Spring Boot 項目中引入該 starter 后,直接在 Service 或 Controller 中使用
PageHelper.startPage(pageNum, pageSize)
即可。
-
PageHelper
的參數模式擴展- 核心功能擴展:除了
PageHelper.startPage
,PageHelper
本身支持更靈活的參數傳遞:- 方法參數傳遞 (需配置
support-methods-arguments: true
):// Mapper 接口 List<User> selectUsers(@Param("name") String name, @Param("pageNum") int pageNum, @Param("pageSize") int pageSize);
// Service 調用 (無需顯式調用 startPage) List<User> users = userMapper.selectUsers("John", 2, 10); PageInfo<User> pageInfo = new PageInfo<>(users);
RowBounds
參數傳遞 (較舊方式,優先級低于startPage
):List<User> users = sqlSession.selectList("selectUsers", null, new RowBounds(2, 10));
- 方法參數傳遞 (需配置
- 核心功能擴展:除了
-
PageInfo
的增強- 雖然
PageInfo
本身是核心的一部分,但它提供的豐富分頁信息是其強大擴展性的體現:getTotal()
:總記錄數。getPages()
:總頁數。getPageNum()
:當前頁碼。getPageSize()
:每頁條數。getList()
:當前頁的數據列表。isIsFirstPage()
/isIsLastPage()
:是否第一頁/最后一頁。hasPreviousPage()
/hasNextPage()
:是否有上一頁/下一頁。getPrePage()
/getNextPage()
:上一頁/下一頁頁碼。getNavigatepageNums()
:所有導航頁碼(如 [1,2,3,4,5])。
- 這極大地簡化了將分頁信息返回給前端的工作。
- 雖然
三、使用 PageHelper 擴展的注意事項
PageHelper.startPage
的調用位置:- 必須緊挨著需要分頁的 MyBatis 查詢方法調用之前。中間不能有其它可能觸發查詢的操作(如調用另一個查詢方法)。
- 線程安全:
PageHelper.startPage
內部使用ThreadLocal
保存分頁參數。這意味著它是線程安全的,但也意味著分頁參數只對當前線程的緊接著的下一次查詢有效。查詢完成后,ThreadLocal
會被自動清理。在異步、多線程或復雜調用鏈中要特別注意調用時機。
PageInfo
的構造:- 傳入
PageInfo
構造器的List
對象,必須是PageHelper.startPage
后執行分頁查詢返回的那個List
。這個List
實際上是一個Page
對象(實現了List
接口),包含了分頁信息。如果用其他List
構造PageInfo
,信息會錯誤。
- 傳入
- 數據庫方言 (
dialect
):- 確保配置正確的數據庫方言,或讓插件自動檢測(通常可行)。錯誤的方言會導致生成錯誤的分頁 SQL。
reasonable
參數:- 建議開啟 (
reasonable: true
),避免用戶傳入非法頁碼導致空數據或錯誤。
- 建議開啟 (
page-size-zero
:- 如果業務有“pageSize=0 時返回所有數據”的需求,配置
page-size-zero: true
。注意此時PageInfo
的total
是實際數據條數(可能很大),pages
為 1。
- 如果業務有“pageSize=0 時返回所有數據”的需求,配置
- 避免與
RowBounds
混用:- 如果同時使用了
PageHelper.startPage
和RowBounds
參數,PageHelper.startPage
的優先級更高。
- 如果同時使用了
四、總結
- 核心
PageHelper
:提供了 MyBatis 物理分頁的核心攔截能力和基礎 API (startPage
,PageInfo
)。 - 關鍵擴展
pagehelper-spring-boot-starter
:極大簡化了在 Spring Boot 項目中的集成和使用,是當前最推薦的使用方式,實現了開箱即用。 - 參數模式擴展:提供
startPage
之外更靈活的傳參方式(方法參數、RowBounds
),適應不同編碼風格。 PageInfo
對象:作為核心功能的一部分,提供了強大的分頁信息封裝能力,是返回給前端的理想數據結構。
選擇建議:對于 Spring Boot 項目,直接使用 pagehelper-spring-boot-starter
是最佳實踐。充分利用其自動配置和屬性配置,結合 PageHelper.startPage
和 PageInfo
,可以非常高效、簡潔地實現功能強大且信息完整的分頁功能。理解核心原理和注意事項(尤其是 startPage
的調用位置和線程特性)是避免踩坑的關鍵。
如果你有特定的 PageHelper 擴展需求(比如集成到其他框架,或者自定義分頁邏輯),可以進一步探討其 SPI 機制或自定義攔截器實現。