【Mybatis原始碼分析】13-記一次PageHelper reasonable引數使用不當造成的死迴圈
阿新 • • 發佈:2018-12-22
問題描述及原因
使用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引數。