PageHelper 关闭COUNT(0)查询 以及PageHelper 的分页原理分析
pagehelper 關閉count(0)查詢 以及pagehelper的分頁原理分析
情景再現:在給移動端提供分頁查詢數據接口時,知道他們不需要總條數。但是使用pagehelper 分頁查詢打印的sql總是會查詢兩次,先統計條數,在進行列表查詢。對于有點強迫癥的我來說,很不爽。于是開始查資料追源碼。
于是找到了pagehelper的分頁對象: com.github.pagehelper.Page; 其中一個屬性count默認是true,默認會執行count查詢/*** 包含count查詢*/private boolean count = true;1.關閉count()查詢
在執行分頁列表查詢前添加
PageHelper.startPage(page, size, false);
成功關閉count()查詢
PageHelper中的其他方法也可以關閉count()查詢,請讀者自行查閱;
2.拋出問題
本來事情到此已經完美解決,但是因為我們是自己定義了一個Page對象(其實就是com.github.pagehelper.Page,寫在本地的一個pojo)。查詢的條件封裝在一個對象中,并繼承自定義的Page,然后嘗試在自定義的Page中設置count為false,發現并不能生效。
3.原因查找
1)在com.github.pagehelper.util.PageObjectUtil類中下面方法中找到了設置count屬性的邏輯,
調用getParamValue(paramsObject, “count”, false);
2)從下圖中的debug中可以看出getParamValue(paramsObject, “count”, false); 返回null,修改count屬性失敗
3)分析問題
使用PageHelper設置屬性就能生效,是因為PageHelper設置屬性的時候創建了一個本地的Page對象,并存儲到本地。如下面的代碼:
在進行判斷是否進行count查詢的時候查找的是PageHelper中的page對象,所以設置的屬性能夠生效
2)在com.github.pagehelper.PageInterceptor中有是否執行count查詢的條件@Overridepublic Object intercept(Invocation invocation) throws Throwable {......//判斷是否需要進行 count 查詢if (dialect.beforeCount(ms, parameter, rowBounds)) {String countMsId = msId + countSuffix;Long count;//先判斷是否存在手寫的 count 查詢........}} 類位置:com.github.pagehelper.dialect.AbstractHelperDialect#beforeCount@Overridepublic boolean beforeCount(MappedStatement ms, Object parameterObject, RowBounds rowBounds) {Page page = getLocalPage();return !page.isOrderByOnly() && page.isCount();}page.isOrderByOnly() boolean類型 默認false,page.isCount()默認true;所以修改了page.isCount()為false
后,能夠關閉count(0)查詢
4.討論一個問題,為什么使用本地對象也能夠使PageHelper 進行分頁?
有下面方法可知:只要參數中有pageSize和pageNum,PageHelper 就會自動創建PageHelper 中的pege對象 實現分頁邏輯。
路徑:com.github.pagehelper.util.PageObjectUtil#getPageFromObject
5.PageHelper 實現分頁的原理
在執行分頁sql拼接時,在sql后拼接limit進行分頁,在調用方言的時候拼接分頁參數
1)路徑:com.github.pagehelper.PageInterceptor#intercept......//判斷是否需要進行分頁查詢if (dialect.beforePage(ms, parameter, rowBounds)) {//生成分頁的緩存 keyCacheKey pageKey = cacheKey;//處理參數對象parameter = dialect.processParameterObject(ms, parameter, boundSql, pageKey);//調用方言獲取分頁 sqlString pageSql = dialect.getPageSql(ms, boundSql, parameter, rowBounds, pageKey);BoundSql pageBoundSql = new BoundSql(configuration, pageSql, boundSql.getParameterMappings(), parameter);//設置動態參數for (String key : additionalParameters.keySet()) {pageBoundSql.setAdditionalParameter(key, additionalParameters.get(key));}//執行分頁查詢resultList = executor.query(ms, parameter, RowBounds.DEFAULT, resultHandler, pageKey, pageBoundSql);} else {//不執行分頁的情況下,也不執行內存分頁resultList = executor.query(ms, parameter, RowBounds.DEFAULT, resultHandler, cacheKey, boundSql);}.......2)路徑:com.github.pagehelper.dialect.helper.MySqlDialect#getPageSql@Overridepublic String getPageSql(String sql, Page page, CacheKey pageKey) {StringBuilder sqlBuilder = new StringBuilder(sql.length() + 14);sqlBuilder.append(sql);if (page.getStartRow() == 0) {sqlBuilder.append(" LIMIT ? ");} else {sqlBuilder.append(" LIMIT ?, ? ");}pageKey.update(page.getPageSize());return sqlBuilder.toString();}PageHelper自定義count(*)查詢
因數據量太大,使用分頁插件PageHelper解析sql,執行sql時會count一遍總計錄數,此時會將數據庫卡死;
使用分頁插件執行,會嵌套一層SELECT COUNT(*) FROM (主sql) tmp_count
SELECT count(*) FROM (SELECTc.company_name,c.company_type,...FROM company cINNER JOIN t_seller ts ON ts.city_site_id = c.city_site_id....WHERE c.city_site_id = 1) tmp_count希望自定義個cout方法統計總記錄數,刪減不必要的表關聯、字段,
應如何入手?
最新版的PageHelper支持自定義count,參考https://github.com/pagehelper/Mybatis-PageHelper/blob/master/wikis/zh/Changelog.md#504—2017-08-01
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的PageHelper 关闭COUNT(0)查询 以及PageHelper 的分页原理分析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python精要(66)—类(3)-文档
- 下一篇: java如何将String转换为enum