前提:為適配項目發展,完善項目生態,並貼合微服務的環境,最近在對項目進行升級改造,有SpringMVC架構升級為SpringBoot項目,升級過程還比較順利,並完成大部分功能測試和驗證。
突然產品說系統管理功能中用戶的編輯功能突然失效,經過排查代碼發現在查詢用戶角色的接口中復用的是角色管理分頁查詢的接口,並做了查詢總數判斷,由於此處未進行分頁參數設置,導致查詢總數的count=-1,導致數據加載異常。
回憶下針對pagehelper適配過程,之前使用時4版本,由於springboot使用了2版本,因此升級了pagehelper5,之前4版本無問題,其中代碼業務邏輯是:
int pageNum = entity.getPage() == null ? 0 : entity.getPage().intValue(); int pageSize = entity.getLimit() == null ? 0 : entity.getLimit().intValue(); boolean flag = (pageNum == 0 && pageSize == 0) ? false : true; Page<E> page = PageHelper.startPage(pageNum, pageSize, flag);
很明顯4版本中count標識位設置為false可以正常查詢數據總數,5版本不行,通過設置為true時,驗證后才能通過page.getTotal()獲取分頁查詢的總數。
原因分析:
debug源碼發現,在PageInterceptor(參考Mybatis執行攔截器Interceptor)中在執行:
if (this.dialect.beforeCount(ms, parameter, rowBounds)) {//-----此函判斷為false,未執行查詢總數的操作 String countMsId = msId + this.countSuffix; MappedStatement countMs = this.getExistedMappedStatement(configuration, countMsId); Long count; if (countMs != null) { count = this.executeManualCount(executor, countMs, parameter, boundSql, resultHandler); } else { countMs = (MappedStatement)this.msCountMap.get(countMsId); if (countMs == null) { countMs = MSUtils.newCountMappedStatement(ms, countMsId); this.msCountMap.put(countMsId, countMs); } count = this.executeAutoCount(executor, countMs, parameter, boundSql, rowBounds, resultHandler); } if (!this.dialect.afterCount(count, parameter, rowBounds)) { Object var24 = this.dialect.afterPage(new ArrayList(), parameter, rowBounds); return var24; } }
此時繼續追蹤:
private Dialect dialect; private String default_dialect_class = "com.github.pagehelper.PageHelper";
在PageHelper中:beforeCount執行的三個參數:
ms:具體的要執行的mapper.xml文件
parameter:執行mapper.xml查詢時候傳遞過去的參數
rowBounds:分頁參數:此時為offset:0,limit:2147483647
執行的函數為:com.github.pagehelper.dialect.AbstractHelperDialect
看這段業務邏輯:
public boolean beforeCount(MappedStatement ms, Object parameterObject, RowBounds rowBounds) { Page page = this.getLocalPage(); return !page.isOrderByOnly() && page.isCount(); }
其中:page.isOrderByOnly()是false,我們沒有設置,此時我們邏輯中page.isCount()設置為false,故此時不在去執行查詢總數的操作,如果我們想獲取總數,無論是否分頁我們在創建Page對象時一律設置為true即可。