首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

MyBatis 分頁插件 PageHelper 實戰:零侵入、多數據庫、豐富元數據

     編輯:Java 綜合教學

MyBatis 分頁插件 PageHelper 實戰:零侵入、多數據庫、豐富元數據

PageHelper 是 MyBatis 生態**最流行、最省心**的分頁插件,支持 Oracle、MySQL、MariaDB、SQLite、HsqlDB、PostgreSQL 六大數據庫。

一、配置攔截器

<plugins>
  <plugin interceptor="com.github.pagehelper.PageHelper">
    <property name="dialect" value="mysql"/> <!-- 數據庫類型 -->
    <property name="rowBoundsWithCount" value="true"/> <!-- RowBounds 也查總數 -->
    <property name="pageSizeZero" value="true"/> <!-- pageSize=0 查全部 -->
    <property name="reasonable" value="true"/> <!-- 頁碼越界自動修正 -->
  </plugin>
</plugins>

二、核心 API 兩種用法

1. 簡單模式:PageHelper.startPage + 強轉 Page<E>

// 查第 1 頁,每頁 10 條
PageHelper.startPage(1, 10);
List<Country> list = countryMapper.selectIf(1);

// 強轉獲取分頁元數據
Page<Country> page = (Page<Country>) list;
long total = page.getTotal();        // 總記錄數
int pages = page.getPages();         // 總頁數
int pageNum = page.getPageNum();     // 當前頁碼
int pageSize = page.getPageSize();   // 每頁大小
boolean hasNext = page.isHasNextPage();

2. 豐富模式:PageInfo 包裝結果

PageHelper.startPage(1, 10);
List<Country> list = countryMapper.selectAll();

// 包裝
PageInfo<Country> pageInfo = new PageInfo<>(list);

// 完整元數據
assertEquals(1, pageInfo.getPageNum());
assertEquals(10, pageInfo.getPageSize());
assertEquals(1, pageInfo.getStartRow());      // 當前頁起始行號 (1-based)
assertEquals(10, pageInfo.getEndRow());       // 當前頁結束行號
assertEquals(183, pageInfo.getTotal());       // 總記錄數
assertEquals(19, pageInfo.getPages());        // 總頁數
assertEquals(1, pageInfo.getFirstPage());     // 首頁頁碼
assertEquals(8, pageInfo.getLastPage());      // 尾頁頁碼
assertEquals(true, pageInfo.isFirstPage());
assertEquals(false, pageInfo.isLastPage());
assertEquals(false, pageInfo.isHasPreviousPage());
assertEquals(true, pageInfo.isHasNextPage());
assertEquals(8, pageInfo.getNavigatePages()); // 導航頁碼數
assertEquals(1, pageInfo.getNavigateFirstPage());
assertEquals(8, pageInfo.getNavigateLastPage());
assertEquals(8, pageInfo.getNavigatepageNums().length);

三、進階技巧

場景解決方案
手動控制 count 查詢PageHelper.startPage(pageNum, pageSize, false) 第三參數 count=false 跳過總數查詢,極大提升大表性能
不想污染 ThreadLocal使用 PageHelper.offsetPage(offset, limit) (MyBatis 3.5+) 無 ThreadLocal,線程安全
Spring Boot 整合引入 pagehelper-spring-boot-starter,application.yml 配置 pagehelper.helper-dialect=mysql
多數據源每個 SqlSessionFactory 獨立配置插件,或使用 PageHelper.autoDialect=true 自動識別
分頁參數來自前端Controller 直接透傳 pageNum/pageSize,配合 reasonable=true 防止非法值

四、原理速覽

  1. 攔截 Executor.query(),解析 MappedStatement 獲取原始 SQL。
  2. 根據 dialect 方言生成分頁 SQL:MySQL LIMIT offset, size、Oracle ROWNUM 子查詢、PostgreSQL LIMIT/OFFSET 等。
  3. 執行 SELECT COUNT(*) FROM (original_sql) tmp 獲取總數(可關閉)。
  4. 將結果封裝為 Page<E>(繼承 ArrayList),攜帶分頁屬性。

五、避坑指南

  • 只對緊隨其後的第一個 select 生效,中間插入其他查詢會失效。
  • 不要在循環/並發中共用 startPage,ThreadLocal 會互相覆蓋,改用 offsetPage 或手動 clearPage()。
  • 嵌套調用:外層 startPage 會被內層覆蓋,需手動保存恢復或使用 PageHelper.clearPage()。

PageHelper 讓分頁從「業務邏輯」變成「基礎設施」,專注業務才是正道。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved