MybatisPlus的分页插件拦截器解析sql流程(自用复习)

分页插件的部分源码(浅)

本文章根据*乎博主“京思祺”博主的文章引领理解的

配置bean:

@Configuration
public class MybatisPlusConfig {

    @Bean
    public PaginationInterceptor paginationInterceptor() {

        return new PaginationInterceptor();
    }

}

下面是PaginationInterceptor中**intercept()**部分的源码

public Object intercept(Invocation invocation) throws Throwable {
        StatementHandler statementHandler = (StatementHandler)PluginUtils.realTarget(invocation.getTarget());
        MetaObject metaObject = SystemMetaObject.forObject(statementHandler);
        this.sqlParser(metaObject);//解析sql
		//sql拦截器,可以设置id属性拦截具体sql
        MappedStatement mappedStatement = (MappedStatement)metaObject.getValue("delegate.mappedStatement");
		//判断是否sql语句
        if (SqlCommandType.SELECT == mappedStatement.getSqlCommandType() && StatementType.CALLABLE != mappedStatement.getStatementType()) {
			//获取sql语句中保存的参数信息
            BoundSql boundSql = (BoundSql)metaObject.getValue("delegate.boundSql");
            Object paramObj = boundSql.getParameterObject();
            IPage<?> page = null;
			//判断保存的对象是否是ipage对象
            if (paramObj instanceof IPage) {
                page = (IPage)paramObj;
            } else if (paramObj instanceof Map) {
				//判断是否为map对象,是的话获取map迭代器,判断map中是否有ipage对象
                Iterator var8 = ((Map)paramObj).values().iterator();

                while(var8.hasNext()) {
                    Object arg = var8.next();
                    if (arg instanceof IPage) {
                        page = (IPage)arg;
                        break;
                    }
                }
            }
			//如果对象不为空
            if (null != page && page.getSize() >= 0L) {
				//处理单条页数限制
                if (this.limit > 0L && this.limit <= page.getSize()) {
                    page.setSize(this.limit);
                }

				//取出sql建立数据库连接
                String originalSql = boundSql.getSql();
                Connection connection = (Connection)invocation.getArgs()[0];
				//获取数据库类型 DBType是一个枚举类,里面标识了各大数据库系统
                DbType dbType = StringUtils.isNotEmpty(this.dialectType) ? DbType.getDbType(this.dialectType) : JdbcUtils.getDbType(connection.getMetaData().getURL());
                if (page.isSearchCount()) {
					//优化count
                    SqlInfo sqlInfo = SqlParserUtils.getOptimizeCountSql(page.optimizeCountSql(), this.countSqlParser, originalSql);
					//查询count
                    this.queryTotal(this.overflow, sqlInfo.getSql(), mappedStatement, boundSql, page, connection);
                    if (page.getTotal() <= 0L) {
                        return null;
                    }
                }

				//连接orderby 自定义排序
                String buildSql = concatOrderBy(originalSql, page);
				//重构sql,加了个limit()达到分页效果
                DialectModel model = DialectFactory.buildPaginationSql(page, buildSql, dbType, this.dialectClazz);
                Configuration configuration = mappedStatement.getConfiguration();
                List<ParameterMapping> mappings = new ArrayList(boundSql.getParameterMappings());
                Map<String, Object> additionalParameters = (Map)metaObject.getValue("delegate.boundSql.additionalParameters");
                model.consumers(mappings, configuration, additionalParameters);
                metaObject.setValue("delegate.boundSql.sql", model.getDialectSql());
                metaObject.setValue("delegate.boundSql.parameterMappings", mappings);
				//执行sql
                return invocation.proceed();
            } else {
                return invocation.proceed();
            }
        } else {
            return invocation.proceed();
        }
    }

大概的流程就是:通过invocation来获取statementHandler再获取原生的sql语句,利用BoundSql 中保存的用户传入的数据来判断是否是ipage的实例,是的话执行接下来的sql解析缓解,不是的话直接跳过进行sql查询返回。在sql解析这个分支中先是判断处理了单条sql执行返回的条数SetSize(),然后建立数据库连接获取当前数据库系统的类型,接下来就是优化count和加入limit执行条件来填充ipage对象中的属性执行sql。

本文章内容仅供参考,所写内容为本人自己理解,只是稍微了解了一下大概流程,内部细节没有多看,如果错误之处欢迎大佬指正,谢谢

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值