以下是 MyBatis-Plus 中 PaginationInterceptor
分页部分的简化版源码,以便理解分页的实现原理:
public class PaginationInterceptor implements Interceptor { @Override public Object intercept(Invocation invocation) throws Throwable { // 从 Invocation 对象中获取原始的 MappedStatement 对象 MappedStatement ms = (MappedStatement) invocation.getArgs()[0]; // 判断是否需要进行分页处理 if (ms.getId().matches(".+\\.selectPage$")) { // 从 BoundSql 对象中获取原始的 SQL 语句和参数对象 BoundSql boundSql = ms.getBoundSql(invocation.getArgs()[1]); String originalSql = boundSql.getSql(); Object parameterObject = boundSql.getParameterObject(); // 解析分页参数 Page<?> page = findPageObject(parameterObject); // 改写 SQL 语句,增加分页的限制条件 String newSql = "SELECT * FROM (" + originalSql + ") tmp LIMIT ?, ?"; List<Object> newParameters = new ArrayList<>(boundSql.getParameterValues()); newParameters.add(page.getOffset()); newParameters.add(page.getSize()); // 将修改后的 SQL 和参数对象重新设置到 BoundSql 对象中 BoundSql newBoundSql = new BoundSql(ms.getConfiguration(), newSql, boundSql.getParameterMappings(), newParameters); // 将修改后的 BoundSql 对象重新设置到 MappedStatement 对象中 MappedStatement newMs = createMappedStatement(ms, newBoundSql); invocation.getArgs()[0] = newMs; } // 继续执行原始的 SQL 语句 return invocation.proceed(); } private Page<?> findPageObject(Object parameterObject) { if (parameterObject instanceof Page) { return (Page<?>) parameterObject; } else if (parameterObject instanceof Map) { Map<?, ?> paramMap = (Map<?, ?>) parameterObject; for (Object value : paramMap.values()) { if (value instanceof Page) { return (Page<?>) value; } } } return null; } private MappedStatement createMappedStatement(MappedStatement ms, BoundSql boundSql) { MappedStatement.Builder builder = new MappedStatement.Builder(ms.getConfiguration(), ms.getId(), new StaticSqlSource(boundSql), ms.getSqlCommandType()); builder.parameterMap(ms.getParameterMap()); builder.resultMaps(ms.getResultMaps()); builder.cache(ms.getCache()); builder.useCache(ms.isUseCache()); return builder.build(); } // 其他方法和属性省略... }
上述代码是一个简化版的 PaginationInterceptor
类的源码,主要包括拦截方法 intercept
和辅助方法 findPageObject
、createMappedStatement
。在拦截方法中,通过判断 MappedStatement 对象的 ID 是否匹配以 .selectPage
结尾的命名规则,来确定是否需要进行分页处理。如果需要分页,就从参数中获取分页参数对象 Page
,然后解析分页参数并对 SQL 语句进行改写。最后,再将修改后的 MappedStatement 对象传递给后续处理逻辑。
需要注意的是,以上源码中省略了某些细节处理,例如对 Count SQL 语句的处理、分页插件的配置、分页参数的校验等。完整的源码可以在 MyBatis-Plus 的代码库中查看。此外,MyBatis-Plus 还支持其他类型的分页方式和分页插件,具体实现可能会有所不同。上述代码仅用于简化示例,以便更好地理解分页的原理。
标签: 来源:
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。