MyBatis源码阅读——MyBatis插件PageHelper的实现过程

前言

在之前的文章 MyBatis源码阅读——MyBatis插件原理中我们已经知道MyBatis的插件是如何运行的,这篇文章中,我们将去了解MyBatis常用插件com.github.pagehelper.PageHelper的实现过程

示例代码

https://github.com/yuyufeng1994/learn-mybatis/blob/master/mybatis-demo/src/main/java/top/yuyufeng/learn/mybatis/demo/Demo5Plugin.java

PageHelper拦截过程

设置完成后,Executor的每个method = “query” 的方法执行都会被代理执行
PageHelper.java->intercept()

	/**
	     * Mybatis拦截器方法
	     *
	     * @param invocation 拦截器入参
	     * @return 返回执行结果
	     * @throws Throwable 抛出异常
	     */
	    public Object intercept(Invocation invocation) throws Throwable {
	        if (autoDialect) {
	            initSqlUtil(invocation);
	        }
	        return sqlUtil.processPage(invocation);
	    }

sqlUtil.processPage(invocation)

  /**
     * Mybatis拦截器方法
     *
     * @param invocation 拦截器入参
     * @return 返回执行结果
     * @throws Throwable 抛出异常
     */
    private Object _processPage(Invocation invocation) throws Throwable {
        final Object[] args = invocation.getArgs();
        RowBounds rowBounds = (RowBounds) args[2];
        if (SqlUtil.getLocalPage() == null && rowBounds == RowBounds.DEFAULT) {
            if (OrderByHelper.getOrderBy() != null) {
                OrderByHelper.processIntercept(invocation);
            }
            return invocation.proceed();
        } else {
            //获取原始的ms
            MappedStatement ms = (MappedStatement) args[0];
            //判断并处理为PageSqlSource
            if (!isPageSqlSource(ms)) {
                processMappedStatement(ms, parser);
            }
            //忽略RowBounds-否则会进行Mybatis自带的内存分页
            args[2] = RowBounds.DEFAULT;
            //分页信息
            Page page = getPage(rowBounds);
            //pageSizeZero的判断
            if ((page.getPageSizeZero() != null && page.getPageSizeZero()) && page.getPageSize() == 0) {
                COUNT.set(null);
                //执行正常(不分页)查询
                Object result = invocation.proceed();
                //得到处理结果
                page.addAll((List) result);
                //相当于查询第一页
                page.setPageNum(1);
                //这种情况相当于pageSize=total
                page.setPageSize(page.size());
                //仍然要设置total
                page.setTotal(page.size());
                //返回结果仍然为Page类型 - 便于后面对接收类型的统一处理
                return page;
            }

            //简单的通过total的值来判断是否进行count查询
            if (page.isCount()) {
                COUNT.set(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;
                }
            }
            //pageSize>0的时候执行分页查询,pageSize<=0的时候不执行相当于可能只返回了一个count
            if (page.getPageSize() > 0 &&
                    ((rowBounds == RowBounds.DEFAULT && page.getPageNum() > 0)
                            || rowBounds != RowBounds.DEFAULT)) {
                //将参数中的MappedStatement替换为新的qs
                COUNT.set(null);
                BoundSql boundSql = ms.getBoundSql(args[1]);
                args[1] = parser.setPageParameter(ms, args[1], boundSql, page);
                COUNT.set(Boolean.FALSE);
                //执行分页查询
                Object result = invocation.proceed();
                //得到处理结果
                page.addAll((List) result);
            }
            //返回结果
            return page;
        }
    }

你可能感兴趣的:(Java,MyBatis源码阅读)