PageHelper pagination fails, only the first page can be found
1. phenomenon
-
The pagination code is as follows:
int pageId = Constants.ONE; boolean isHasNextPage; do { PageHelper.startPage(pageId, Constants.DEFAULT_PAGE_SIZE); List<String> projectIdList = marketingConsStageDAO.getAllProjectId(); PageInfo<String> pageInfo = new PageInfo<>(projectIdList); // 此处省略业务逻辑 isHasNextPage = pageInfo.isHasNextPage(); pageId++; } while (isHasNextPage);
-
marketingConsStageDAO.getAllProjectId()
code show as below:public List<String> getAllProjectId() { Weekend<MarketingConsStage> weekend = Weekend.of(MarketingConsStage.class, true, true); weekend.selectProperties("projectId"); weekend.setDistinct(true); return marketingConsStageMapper.selectByExample(weekend) .stream() .map(MarketingConsStage::getProjectId) .collect(Collectors.toList()); }
-
marketingConsStageDAO.getAllProjectId()
It should return more than 20,000 pieces of data, so it is expected thatdo-while
the loop will be executed many times, but the first page is foundisHasNextPage
, and the loopfalse
cannot be continued ;do-while
2. Reason
-
Go ahead
debug
and hit the breakpoint atPageInfo<String> pageInfo = new PageInfo<>(projectIdList);
This line, and then found that the return type
projectIdList
isArrayList
; -
Take a look at
PageInfo
the construction method:/** * 包装Page对象 * * @param list page结果 * @param navigatePages 页码数量 */ public PageInfo(List<T> 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(); //由于结果是>startRow的,所以实际的需要+1 if (this.size == 0) { this.startRow = 0; this.endRow = 0; } else { this.startRow = page.getStartRow() + 1; //计算实际的endRow(最后一页的时候特殊) 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) { calcByNavigatePages(navigatePages); } }
-
It can be seen that because
projectIdList
it isArrayList
a type, when the object is created , the logic ofpageInfo
the total number of pages goes directly , resulting in paging failure;this.pages = this.pageSize > 0 ? 1 : 0;
-
if we will
.stream() .map(MarketingConsStage::getProjectId) .collect(Collectors.toList());
The operation is placed outside the paging query operation, and the code is modified to:
int pageId = Constants.ONE; boolean isHasNextPage; do { PageHelper.startPage(pageId, Constants.DEFAULT_PAGE_SIZE); List<MarketingConsStage> marketingConsStageList = marketingConsStageDAO.getAllProjectId(); PageInfo<MarketingConsStage> pageInfo = new PageInfo<>(marketingConsStageList); List<String> projectIdList = marketingConsStageList.stream() .map(MarketingConsStage::getProjectId) .collect(Collectors.toList()); // 此处省略业务逻辑 isHasNextPage = pageInfo.isHasNextPage(); pageId++; } while (isHasNextPage);
will be
marketingConsStageDAO.getAllProjectId()
modified to:public List<MarketingConsStage> getAllProjectId() { Weekend<MarketingConsStage> weekend = Weekend.of(MarketingConsStage.class, true, true); weekend.selectProperties("projectId"); weekend.setDistinct(true); return marketingConsStageMapper.selectByExample(weekend); }
Then
debug
you will find thatmarketingConsStageList
it is aPage
type variable, and the paging function is normal at this time;
3. Working principle of PageHelper
PageHelper
It is aMyBatis
pagination plug-in, which can help us perform paging processing when querying data. When we callPageHelper.startPage(pageNum, pageSize)
the method, it will be used at the bottom to save the paging parameters of the current thread, and then rewrite the statementThreadLocal
through the interceptor to realize paging query.SQL
- After we call
PageHelper.startPage(pageNum, pageSize)
the method, the query statement executed immediatelySQL
will bePageHelper
intercepted and rewritten, so that only the data of the specified number of pages and the number of records per page will be returned when querying the results.PageHelper
The query result will be encapsulated into anPage
object, whichPage
contains the total number of records of the query result, the current page number, the number of records per page, and the data list of the query result. - Therefore, when we call the query method, the returned object
list
can bePageHelper
wrapped intoPage
an object. This is becausePageHelper
the query result is encapsulated at the bottom layer, and the query result isPage
returned to the caller in the form of an object. The caller canPage
obtain various information of the query result through the object, such as the total number of records, the number of current pages, the number of records per page, etc., and can alsoPage
obtain the data list of the query result through the object. - In short,
PageHelper
the process of implementing pagination query can be summarized as: enable paging query -> execute query operation -> return the query result list to the caller, and wrap it in the form of object -Page
> the callerPage
obtains various information of paging query through the object .