Fixing Incorrect Total Count in PageHelper Pagination Using PageInfo
This article analyzes why the total record count returned by PageHelper mismatches the actual number of rows, examines the underlying PageInfo and PageSerializable source code, and provides a concrete solution that avoids type conversion and directly constructs PageInfo from the mapper result to ensure accurate pagination.
The article discusses an issue encountered when using the PageHelper pagination plugin where the returned total value incorrectly matches the pageSize instead of the actual total number of records. It first outlines the problem description, showing that the database count exceeds the returned total and presenting the relevant screenshot.
Problem Analysis
By inspecting the source code of PageInfo<T> , it is observed that the constructor does not handle the total field when the supplied list is not an instance of Page . The parent class PageSerializable sets total to list.size() in such cases, which explains the discrepancy when the mapper's result list is wrapped into a different object.
public class PageInfo
extends PageSerializable
{
/**
* 包装Page对象
* @param list page结果
* @param navigatePages 页码数量
*/
public PageInfo(List
list, int navigatePages) {
super(list);
if (list instanceof Page) {
Page page = (Page) list;
this.pageNum = page.getPageNum();
this.pageSize = page.getPageSize();
this.pages = page.getPages();
this.size = page.size();
if (this.size == 0) {
this.startRow = 0;
this.endRow = 0;
} else {
this.startRow = page.getStartRow() + 1;
this.endRow = this.startRow - 1 + this.size;
}
} else if (list instanceof Collection) {
this.pageNum = 1;
this.pageSize = list.size();
this.pages = this.pageSize > 0 ? 1 : 0;
this.size = list.size();
this.startRow = 0;
this.endRow = list.size() > 0 ? list.size() - 1 : 0;
}
if (list instanceof Collection) {
this.navigatePages = navigatePages;
calcNavigatepageNums();
calcPage();
judgePageBoudary();
}
}
}The parent class implementation:
public PageSerializable(List
list) {
this.list = list;
if (list instanceof Page) {
this.total = ((Page) list).getTotal();
} else {
this.total = list.size();
}
}Debugging confirms that the mapper returns a Page instance, but the code later replaces it with another object, causing total to be set to the list size.
Solution
To avoid the loss of the correct total count, construct PageInfo directly from the mapper's return value without any type conversion or re‑wrapping:
// Correct usage example
PageInfo
pageInfo = new PageInfo<>(mapperMethod(params));Best Practice
When using PageInfo , always pass the original Page object returned by MyBatis mapper to the constructor; do not transform the list into another collection or custom wrapper, as this will cause the total field to be incorrectly calculated.
JD Tech
Official JD technology sharing platform. All the cutting‑edge JD tech, innovative insights, and open‑source solutions you’re looking for, all in one place.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.