PageHelper原理分析 有更新!

  |   0 评论   |   2,817 浏览

    https://www.cnblogs.com/dengpengbo/p/10579631.html

    项目结构:
    834cdbe3c0444a3aa1025fc486d15be2-WX202009021443002x.png

    本次主要讲解PageHelper是如何做到基于Mybatis实现分页的

    正题:

    众所周知,pagehelper是基于mybatis拦截器做到的分页,启用pagehelper实现分页有两个开关
    1.PageHelper.startPage(pageNum, pageSize)
    2.supportMethodsArguments=true 并且mapper.method 参数中包含pageNum 和pageSize字段,并且都不为null时
    

    源码分析:
    下面看下PageHelper的源代码的头部定义

    @Intercepts(@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}))
    
    public class PageHelper implements Interceptor
    

    PageHelper中已经定义了该拦截器拦截的方法是什么

    我们从拦截器的入口开始
    36291d7727b444cb9db0345583ae7b12-1599030224139.jpg

    上图可以得知,首先获取sqlutil 对象实例,然后执行sqlutil.processPage方法
    841a9d4de0c34d638763b0399dc5d932-1599030411392.jpg

    c59645c6bfad412581bfa35e9e9997fe-1599034910314.jpg

    private Page doProcessPage(Invocation invocation, Page page, Object[] args) throws Throwable {
            //保存RowBounds状态
            RowBounds rowBounds = (RowBounds) args[2];
            //获取原始的ms
            MappedStatement ms = (MappedStatement) args[0];
            //判断并处理为PageSqlSource
            if (!isPageSqlSource(ms)) {
                processMappedStatement(ms);
            }
            //设置当前的parser,后面每次使用前都会set,ThreadLocal的值不会产生不良影响
            ((PageSqlSource)ms.getSqlSource()).setParser(parser);
            //忽略RowBounds-否则会进行Mybatis自带的内存分页
            args[2] = RowBounds.DEFAULT;
            //如果只进行排序 或 pageSizeZero的判断
            if (isQueryOnly(page)) {
                return doQueryOnly(page, invocation);
            }
    
            //简单的通过total的值来判断是否进行count查询
            if (page.isCount()) {
                page.setCountSignal(Boolean.TRUE);
                //替换MS
                args[0] = msCountMap.get(ms.getId());
                //查询总数
                Object result = invocation.proceed();
                //还原ms
                args[0] = ms;
                //设置总数
                page.setTotal((Integer) ((List) result).get(0));
                if (page.getTotal() == 0) {
                    return page;
                }
            } else {
                page.setTotal(-1l);
            }
            //pageSize>0的时候执行分页查询,pageSize<=0的时候不执行相当于可能只返回了一个count
            if (page.getPageSize() > 0 &&
                    ((rowBounds == RowBounds.DEFAULT && page.getPageNum() > 0)
                            || rowBounds != RowBounds.DEFAULT)) {
                //将参数中的MappedStatement替换为新的qs
                page.setCountSignal(null);
                BoundSql boundSql = ms.getBoundSql(args[1]);
                args[1] = parser.setPageParameter(ms, args[1], boundSql, page);
                page.setCountSignal(Boolean.FALSE);
                //执行分页查询
                Object result = invocation.proceed();
                //得到处理结果
                page.addAll((List) result);
            }
            //返回结果
            return page;
        }
    

    BoundSql boundSql = ms.getBoundSql(args[1]);
    c3e9f36887b84d1ab3162a87818082fe-1599039392152.jpg

    评论

    发表评论

    validate