mybatis-plus分頁(yè)插件失效探究解決
網(wǎng)上推薦
網(wǎng)上基本上都是推薦配置如下:
@Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor(); mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); return mybatisPlusInterceptor; }
但是,僅僅這么做,就能達(dá)到我們的預(yù)期嗎?
分頁(yè)插件無(wú)效原因
其結(jié)局就是分頁(yè)插件沒(méi)有效果,原因是為什么呢???
圖1
圖2
通過(guò)對(duì)比上面兩張圖可以發(fā)現(xiàn),圖一DefaultSqlSession.selectList()底層調(diào)用Plugin.invoke();圖二DefaultSqlSession.selectList()底層調(diào)用CachingExecutor.query()。
其中,圖一是分頁(yè)插件生效的調(diào)用鏈,圖二是分頁(yè)插件失效的調(diào)用鏈。
也就是說(shuō),分頁(yè)插件失效的原因是,mybatis-plusPlugin類沒(méi)有為分頁(yè)插件攔截器生成Executor代理。
解決方案
具體應(yīng)該怎么做呢?像下面這樣,在構(gòu)建SqlSessionFactory時(shí),需要在MybatisSqlSessionFactoryBean顯示設(shè)置Plugin。
@Bean(name = "defaultSqlSessionFactory") public SqlSessionFactory defaultSqlSessionFactory(){ MybatisSqlSessionFactoryBean bean = new MybatisSqlSessionFactoryBean(); bean.setDataSource(dataSource); //設(shè)置攔截器 bean.setPlugins(mybatisPlusInterceptor); SqlSessionFactory sqlSessionFactory = bean.getObject(); //設(shè)置自動(dòng)提交 sqlSessionFactory.openSession(true); return sqlSessionFactory; }
那么,為分頁(yè)插件生成代理類是在什么時(shí)機(jī)生成呢?先公布答案:
//設(shè)置自動(dòng)提交 sqlSessionFactory.openSession(true);
調(diào)用鏈如下
圖3
咱再看細(xì)節(jié):DefaultSqlSessionFactory.openSessionFromDataSource()詳情:
private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) { Transaction tx = null; try { final Environment environment = configuration.getEnvironment(); final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment); tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit); //這步很關(guān)鍵,創(chuàng)建執(zhí)行者實(shí)例 final Executor executor = configuration.newExecutor(tx, execType); return new DefaultSqlSession(configuration, executor, autoCommit); } catch (Exception e) { closeTransaction(tx); // may have fetched a connection so lets call close() throw ExceptionFactory.wrapException("Error opening session. Cause: " + e, e); } finally { ErrorContext.instance().reset(); } }
Configuration.newExecutor()詳情:
public Executor newExecutor(Transaction transaction, ExecutorType executorType) { executorType = executorType == null ? defaultExecutorType : executorType; executorType = executorType == null ? ExecutorType.SIMPLE : executorType; Executor executor; if (ExecutorType.BATCH == executorType) { executor = new BatchExecutor(this, transaction); } else if (ExecutorType.REUSE == executorType) { executor = new ReuseExecutor(this, transaction); } else { executor = new SimpleExecutor(this, transaction); } if (cacheEnabled) { executor = new CachingExecutor(executor); } //對(duì)上面的executor進(jìn)行代理(目的是把插件和執(zhí)行器封裝為代理類) executor = (Executor) interceptorChain.pluginAll(executor); return executor; }
MybatisPlusInterceptor.pluginAll();
public Object pluginAll(Object target) { for (Interceptor interceptor : interceptors) { target = interceptor.plugin(target); } return target; }
通過(guò)上面的重點(diǎn)code展示,我們大致了解了部分重要節(jié)點(diǎn)中分頁(yè)插件代理類生成的邏輯。接下來(lái)我們繼續(xù)了解具體分頁(yè)插件工作的效果。
圖4
public boolean willDoQuery(){ if (countMs != null) { countSql = countMs.getBoundSql(parameter); } else { countMs = buildAutoCountMappedStatement(ms); //生成查詢count SQL String countSqlStr = autoCountSql(page, boundSql.getSql()); PluginUtils.MPBoundSql mpBoundSql = PluginUtils.mpBoundSql(boundSql); //構(gòu)建BoundSql countSql = new BoundSql(countMs.getConfiguration(), countSqlStr, mpBoundSql.parameterMappings(), parameter); PluginUtils.setAdditionalParameter(countSql, mpBoundSql.additionalParameters()); } //查詢 count 數(shù)值 List<Object> result = executor.query(countMs, parameter, rowBounds, resultHandler, cacheKey, countSql); }
接下來(lái),PaginationInnerInterceptor.beforeQuery()生成分頁(yè)sql;
最終MybatisPlusInterceptor.intercept()里面的executor.query()執(zhí)行分頁(yè)sql。
以上就是mybatis-plus分頁(yè)插件失效探究解決的詳細(xì)內(nèi)容,更多關(guān)于mybatis plus分頁(yè)插件失效的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
深入理解JVM之Java對(duì)象的創(chuàng)建、內(nèi)存布局、訪問(wèn)定位詳解
這篇文章主要介紹了深入理解JVM之Java對(duì)象的創(chuàng)建、內(nèi)存布局、訪問(wèn)定位,結(jié)合實(shí)例形式詳細(xì)分析了Java對(duì)象的創(chuàng)建、內(nèi)存布局、訪問(wèn)定位相關(guān)概念、原理、操作技巧與注意事項(xiàng),需要的朋友可以參考下2019-09-09JAVA?IDEA項(xiàng)目打包為jar包的步驟詳解
在Java開(kāi)發(fā)中我們通常會(huì)將我們的項(xiàng)目打包成可執(zhí)行的Jar包,以便于在其他環(huán)境中部署和運(yùn)行,下面這篇文章主要給大家介紹了關(guān)于JAVA?IDEA項(xiàng)目打包為jar包的相關(guān)資料,需要的朋友可以參考下2024-08-08Kotlin-Coroutines中的async與await異步協(xié)程管理
這篇文章主要為大家介紹了Kotlin-Coroutines中的async與await異步協(xié)程管理,提升程序性能解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-10-10SpringBoot之RestTemplate在URL中轉(zhuǎn)義字符的問(wèn)題
這篇文章主要介紹了SpringBoot之RestTemplate在URL中轉(zhuǎn)義字符的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-06-06在SpringBoot 中從application.yml中獲取自定義常量方式
這篇文章主要介紹了在SpringBoot 中從application.yml中獲取自定義常量方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-04-04java boolean占用內(nèi)存大小說(shuō)明
這篇文章主要介紹了java boolean占用內(nèi)存大小,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-06-06