上一篇Mybatis源碼分析剛講過PageHelper分頁機制https://blog.csdn.net/shenchaohao12321/article/details/80168655,但是沒有分析reasonable參數,碰到這次自己遇上個坑總結一下。
問題描述及原因
使用Mybatis PageHelper插件做了表的分頁查詢,要求查詢符合某一條件的所有記錄做處理,就寫了一個疊代器在while循環裡對每條記錄做處理,直到符合條件的記錄都處理完程式傳回。代碼如下
public class ReconPaymentIterator implements Iterator<ReconPayment> {
private ReconPaymentMapper reconPaymentMapper;
private ReconPaymentExample reconPaymentExample;
private int pageNum=1;
private Iterator<ReconPayment> iterator;
public ReconPaymentIterator(ReconPaymentMapper reconPaymentMapper, ReconPaymentExample reconPaymentExample){
this.reconPaymentMapper=reconPaymentMapper;
this.reconPaymentExample=reconPaymentExample;
}
@Override
public boolean hasNext() {
if(iterator==null||!iterator.hasNext()){
PageHelper.startPage(pageNum++, 1000);
iterator =reconPaymentMapper.selectByExample(reconPaymentExample).iterator();
}
return iterator.hasNext();
}
@Override
public ReconPayment next() {
return iterator.next();
}
}
public class ReconPaymentIteratorTest extends AbstractPcsChannelReconServiceAppTest {
@Resource
private ReconPaymentMapper reconPaymentMapper;
@Test
public void testReconPaymentIterator(){
ReconPaymentIterator reconPaymentIterator = new ReconPaymentIterator(reconPaymentMapper, new ReconPaymentExample());
while (reconPaymentIterator.hasNext()){
reconPaymentIterator.next();
}
}
}
在上面的單元測試中發現出現了死循環,跟蹤了一下代碼發現原因。PageHelper插件為了統計頁數預設在查詢資料庫記錄前會做一次count查詢的,在上一篇部落格中也有注釋,具體在PageInterceptor的intercept方法中。

就是上圖示紅處,在count查詢查詢後會調用dialect.afterCount()方法。最終調用的是AbstractHelperDialect的afterCount方法。
在得到總數後會調用Page對象的setTotal方法。
如過開啟了reasonable功能,并且使用者傳入的頁數已經大于了總頁數,則會将使用者傳入的pageNum修改為總頁數pages,這樣在count查詢後的分頁記錄查詢中導緻查詢的是最後一頁而不會出現期待的周遊結束。
找到配置檔案原來這個鍋得自己背,從其他項目複制過來的配置檔案直接用了沒注意開啟了reasonable參數。