美文网首页
PageHelper

PageHelper

作者: 白驹过隙_忽然而已 | 来源:发表于2020-11-25 16:27 被阅读0次
        <!-- https://mvnrepository.com/artifact/com.github.pagehelper/pagehelper -->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper-spring-boot-starter</artifactId>
            <version>1.2.5</version>
        </dependency>
    
    1. 使用
    PageHelper.startPage(pageNum, pageSize);
    

    标识接下来的查询会进行分页。跟踪代码:

        /**
         * 开始分页
         *
         * @param pageNum      页码
         * @param pageSize     每页显示数量
         * @param count        是否进行count查询
         * @param reasonable   分页合理化,null时用默认配置
         * @param pageSizeZero true且pageSize=0时返回全部结果,false时分页,null时用默认配置
         */
        public static <E> Page<E> startPage(int pageNum, int pageSize, boolean count, Boolean reasonable, Boolean pageSizeZero) {
            Page<E> page = new Page<E>(pageNum, pageSize, count);
            page.setReasonable(reasonable);
            page.setPageSizeZero(pageSizeZero);
            //当已经执行过orderBy的时候
            Page<E> oldPage = getLocalPage();
            if (oldPage != null && oldPage.isOrderByOnly()) {
                page.setOrderBy(oldPage.getOrderBy());
            }
            setLocalPage(page);      //设置线程分页变量
            return page;
        }
    
    public abstract class PageMethod {
        protected static final ThreadLocal<Page> LOCAL_PAGE = new ThreadLocal<Page>();
        protected static boolean DEFAULT_COUNT = true;
    
        /**
         * 设置 Page 参数
         *
         * @param page
         */
        protected static void setLocalPage(Page page) {
            LOCAL_PAGE.set(page);
        }
    }
    

    这里就是构建一个page对象,PageHelper 父类 PageMethod 有一个ThreadLocal变量,将page对象设置到这个线程变量里。
    具体实现分页的逻辑是通过mybatis Interceptor实现的。这里是实现了一个PageInterceptor来进行通用分页。通过获取线程变量page,根据数据库方言来重新构建sql,设置分页参数。

    public class PageInterceptor implements Interceptor {
        @Override
        public Object intercept(Invocation invocation) throws Throwable {
          ...
                //调用方法判断是否需要进行分页,如果不需要,直接返回结果
                if (!dialect.skip(ms, parameter, rowBounds)) {
                    //反射获取动态参数
                    String msId = ms.getId();
                    Configuration configuration = ms.getConfiguration();
                    Map<String, Object> additionalParameters = (Map<String, Object>) additionalParametersField.get(boundSql);
                    //判断是否需要进行 count 查询
                    if (dialect.beforeCount(ms, parameter, rowBounds)) {
                        String countMsId = msId + countSuffix;
                        Long count;
                        //先判断是否存在手写的 count 查询
                        MappedStatement countMs = getExistedMappedStatement(configuration, countMsId);
                        if(countMs != null){
                            count = executeManualCount(executor, countMs, parameter, boundSql, resultHandler);
                        } else {
                            countMs = msCountMap.get(countMsId);
                            //自动创建
                            if (countMs == null) {
                                //根据当前的 ms 创建一个返回值为 Long 类型的 ms
                                countMs = MSUtils.newCountMappedStatement(ms, countMsId);
                                msCountMap.put(countMsId, countMs);
                            }
                            count = executeAutoCount(executor, countMs, parameter, boundSql, rowBounds, resultHandler);
                        }
                        //处理查询总数
                        //返回 true 时继续分页查询,false 时直接返回
                        if (!dialect.afterCount(count, parameter, rowBounds)) {
                            //当查询总数为 0 时,直接返回空的结果
                            return dialect.afterPage(new ArrayList(), parameter, rowBounds);
                        }
                    }
                    //判断是否需要进行分页查询
                    if (dialect.beforePage(ms, parameter, rowBounds)) {
                        //生成分页的缓存 key
                        CacheKey pageKey = cacheKey;
                        //处理参数对象
                        parameter = dialect.processParameterObject(ms, parameter, boundSql, pageKey);
                        //调用方言获取分页 sql
                        String pageSql = dialect.getPageSql(ms, boundSql, parameter, rowBounds, pageKey);
                        BoundSql pageBoundSql = new BoundSql(configuration, pageSql, boundSql.getParameterMappings(), parameter);
                        //设置动态参数
                        for (String key : additionalParameters.keySet()) {
                            pageBoundSql.setAdditionalParameter(key, additionalParameters.get(key));
                        }
                        //执行分页查询
                        resultList = executor.query(ms, parameter, RowBounds.DEFAULT, resultHandler, pageKey, pageBoundSql);
                    } else {
                        //不执行分页的情况下,也不执行内存分页
                        resultList = executor.query(ms, parameter, RowBounds.DEFAULT, resultHandler, cacheKey, boundSql);
                    }
                } else {
                    //rowBounds用参数值,不使用分页插件处理时,仍然支持默认的内存分页
                    resultList = executor.query(ms, parameter, rowBounds, resultHandler, cacheKey, boundSql);
                }
          ...
        }
    }
    

    拦截后返回Page对象,结合Pagehelper实现分页返回。

    相关文章

      网友评论

          本文标题:PageHelper

          本文链接:https://www.haomeiwen.com/subject/pyuniktx.html