疑问:为什么mybatis-plus可以根据dao中的参数是否包含page对象,给sql拼上对应的limit语句
==ps.这里研究的是最新版本(3.5.11)代码==
1.配置
当执行sql的时候mybatis-plus会对所有SQL语句进行拦截并做各种判断与附加操作(这里只添加分页拦截器),会进入到Mybatis-Plus全局拦截器.
1 2 3 4 5 6
| @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); }
|
2.全局拦截器
主要关注下面这段代码
可以看出,当前sql执行时,被拦截器拦截,发现是查询语句,就会先执行winllDoQuery方法,其次做完在执行 beforeQuery
这两个方法的实现在具体的插件拦截器中,如下面的分页拦截器
1 2 3 4 5 6
| for (InnerInterceptor query : interceptors) { if (!query.willDoQuery(executor, ms, parameter, rowBounds, resultHandler, boundSql)) { return Collections.emptyList(); } query.beforeQuery(executor, ms, parameter, rowBounds, resultHandler, boundSql); }
|
3.分页拦截器
3.1 willDoQuery
先count所有数据,将总数存入分页参数中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| @Override public boolean willDoQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException { IPage<?> page = ParameterUtils.findPage(parameter).orElse(null); if (page == null || page.getSize() < 0 || !page.searchCount() || resultHandler != Executor.NO_RESULT_HANDLER) { return true; } BoundSql countSql; MappedStatement countMs = buildCountMappedStatement(ms, page.countId()); if (countMs != null) { countSql = countMs.getBoundSql(parameter); } else { countMs = buildAutoCountMappedStatement(ms); String countSqlStr = autoCountSql(page, boundSql.getSql()); PluginUtils.MPBoundSql mpBoundSql = PluginUtils.mpBoundSql(boundSql); countSql = new BoundSql(countMs.getConfiguration(), countSqlStr, mpBoundSql.parameterMappings(), parameter); PluginUtils.setAdditionalParameter(countSql, mpBoundSql.additionalParameters()); } CacheKey cacheKey = executor.createCacheKey(countMs, parameter, rowBounds, countSql); List<Object> result = executor.query(countMs, parameter, rowBounds, resultHandler, cacheKey, countSql); long total = 0; if (CollectionUtils.isNotEmpty(result)) { if (o != null) { total = Long.parseLong(o.toString()); } } page.setTotal(total); return continuePage(page); }
|
3.2 beforeQuery
判断数据操作是否有分页参数
1
| IPage<?> page = ParameterUtils.findPage(parameter).orElse(null);
|
处理order拼接
1 2 3 4 5
| List<OrderItem> orders = page.orders(); if (CollectionUtils.isNotEmpty(orders)) { addOrdered = true; buildSql = this.concatOrderBy(buildSql, orders); }
|
处理分页操作
1 2 3 4 5 6 7 8 9 10 11 12
| handlerLimit(page, _limit); IDialect dialect = findIDialect(executor); final Configuration configuration = ms.getConfiguration(); DialectModel model = dialect.buildPaginationSql(buildSql, page.offset(), page.getSize()); PluginUtils.MPBoundSql mpBoundSql = PluginUtils.mpBoundSql(boundSql); List<ParameterMapping> mappings = mpBoundSql.parameterMappings(); Map<String, Object> additionalParameter = mpBoundSql.additionalParameters(); model.consumers(mappings, configuration, additionalParameter); mpBoundSql.sql(model.getDialectSql()); mpBoundSql.parameterMappings(mappings);
|
未完待续。。。。