mybatis-plus分頁插件失效探究解決
網(wǎng)上推薦
網(wǎng)上基本上都是推薦配置如下:
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return mybatisPlusInterceptor;
}但是,僅僅這么做,就能達(dá)到我們的預(yù)期嗎?
分頁插件無效原因
其結(jié)局就是分頁插件沒有效果,原因是為什么呢???

圖1

圖2
通過對(duì)比上面兩張圖可以發(fā)現(xiàn),圖一DefaultSqlSession.selectList()底層調(diào)用Plugin.invoke();圖二DefaultSqlSession.selectList()底層調(diào)用CachingExecutor.query()。
其中,圖一是分頁插件生效的調(diào)用鏈,圖二是分頁插件失效的調(diào)用鏈。
也就是說,分頁插件失效的原因是,mybatis-plusPlugin類沒有為分頁插件攔截器生成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;
}那么,為分頁插件生成代理類是在什么時(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;
}通過上面的重點(diǎn)code展示,我們大致了解了部分重要節(jié)點(diǎn)中分頁插件代理類生成的邏輯。接下來我們繼續(xù)了解具體分頁插件工作的效果。

圖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);
}接下來,PaginationInnerInterceptor.beforeQuery()生成分頁sql;
最終MybatisPlusInterceptor.intercept()里面的executor.query()執(zhí)行分頁sql。
以上就是mybatis-plus分頁插件失效探究解決的詳細(xì)內(nèi)容,更多關(guān)于mybatis plus分頁插件失效的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Java事務(wù)管理學(xué)習(xí)之JDBC詳解
這篇文章主要介紹了Java事務(wù)管理學(xué)習(xí)之JDBC的相關(guān)資料,文中介紹的非常詳細(xì),相信對(duì)大家具有一定的參考價(jià)值,需要的朋友們下面來一起看看吧。2017-03-03
一文詳解SpringBoot如何使用pageHelper做分頁處理
分頁是常見大型項(xiàng)目都需要的一個(gè)功能,PageHelper是一個(gè)非常流行的MyBatis分頁插件,下面就跟隨小編一起來了解下SpringBoot是如何使用pageHelper做分頁處理的吧2025-03-03
Java單例模式實(shí)現(xiàn)靜態(tài)內(nèi)部類方法示例
這篇文章主要介紹了Java單例模式實(shí)現(xiàn)靜態(tài)內(nèi)部類方法示例,涉及構(gòu)造函數(shù)私有化等相關(guān)內(nèi)容,需要的朋友可以了解下。2017-09-09
Spring中BeanFactoryPostProcessors是如何執(zhí)行的
BeanFactoryPostProcessor是Spring容器提供的一個(gè)擴(kuò)展機(jī)制,它允許開發(fā)者在Bean的實(shí)例化和初始化之前對(duì)BeanDefinition進(jìn)行修改和處理,這篇文章主要介紹了你知道Spring中BeanFactoryPostProcessors是如何執(zhí)行的嗎,需要的朋友可以參考下2023-11-11
Java實(shí)現(xiàn)預(yù)覽與打印功能詳解
在?Java?中,打印功能主要依賴?java.awt.print?包,該包提供了與打印相關(guān)的一些關(guān)鍵類,比如?PrinterJob?和?PageFormat,它們構(gòu)成了?Java?打印框架的核心,接下來我們將一步步實(shí)現(xiàn)一個(gè)簡單的預(yù)覽和打印功能,需要的朋友可以參考下2025-07-07
帶你了解Java數(shù)據(jù)結(jié)構(gòu)和算法之二叉樹
這篇文章主要為大家介紹了Java數(shù)據(jù)結(jié)構(gòu)和算法之二叉樹,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助2022-01-01

