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;
        }
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章