zoukankan      html  css  js  c++  java
  • PageHelper原理

    PageHelper是什么

    基于mybatis的一款分页插件,仅用少量代码即可实现分页功能

    查询数量sql怎么生成的

    修改了原生的sqlSource,产生了count的MappedStatement

        public static MappedStatement newCountMappedStatement(MappedStatement ms) {
            MappedStatement.Builder builder = new MappedStatement.Builder(ms.getConfiguration(), ms.getId() + "_COUNT", ms.getSqlSource(), ms.getSqlCommandType());
            builder.resource(ms.getResource());
            builder.fetchSize(ms.getFetchSize());
            builder.statementType(ms.getStatementType());
            builder.keyGenerator(ms.getKeyGenerator());
            if (ms.getKeyProperties() != null && ms.getKeyProperties().length != 0) {
                StringBuilder keyProperties = new StringBuilder();
                for (String keyProperty : ms.getKeyProperties()) {
                    keyProperties.append(keyProperty).append(",");
                }
                keyProperties.delete(keyProperties.length() - 1, keyProperties.length());
                builder.keyProperty(keyProperties.toString());
            }
            builder.timeout(ms.getTimeout());
            builder.parameterMap(ms.getParameterMap());
            //count查询返回值int
            List<ResultMap> resultMaps = new ArrayList<ResultMap>();
            ResultMap resultMap = new ResultMap.Builder(ms.getConfiguration(), ms.getId(), int.class, EMPTY_RESULTMAPPING).build();
            resultMaps.add(resultMap);
            builder.resultMaps(resultMaps);
            builder.resultSetType(ms.getResultSetType());
            builder.cache(ms.getCache());
            builder.flushCacheRequired(ms.isFlushCacheRequired());
            builder.useCache(ms.isUseCache());
    
            return builder.build();
        }
    

    分页sql怎么产生的

    对于不同的数据源做不同的处理,对mysql而言,就是产生了对应的limit语句

    public class MysqlParser extends AbstractParser {
        @Override
        public String getPageSql(String sql) {
            StringBuilder sqlBuilder = new StringBuilder(sql.length() + 14);
            sqlBuilder.append(sql);
            sqlBuilder.append(" limit ?,?");
            return sqlBuilder.toString();
        }
    
        @Override
        public Map<String, Object> setPageParameter(MappedStatement ms, Object parameterObject, BoundSql boundSql, Page<?> page) {
            Map<String, Object> paramMap = super.setPageParameter(ms, parameterObject, boundSql, page);
            paramMap.put(PAGEPARAMETER_FIRST, page.getStartRow());
            paramMap.put(PAGEPARAMETER_SECOND, page.getPageSize());
            return paramMap;
        }
    }
    

    分页参数怎么保存的

    通过startPage方法,将分页参数放到ThreadLocal中

        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 = SqlUtil.getLocalPage();
            if (oldPage != null && oldPage.isOrderByOnly()) {
                page.setOrderBy(oldPage.getOrderBy());
            }
            SqlUtil.setLocalPage(page);
            return page;
        }
    

    插件如何融于mybatis中

    通过注册mybatis插件,PageHelper实现了Interceptor接口,核心的处理逻辑都在intercept方法中

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

    sqlSource的动态判断

        public void processMappedStatement(MappedStatement ms) throws Throwable {
            SqlSource sqlSource = ms.getSqlSource();
            MetaObject msObject = SystemMetaObject.forObject(ms);
            SqlSource pageSqlSource;
            if (sqlSource instanceof StaticSqlSource) {
                pageSqlSource = new PageStaticSqlSource((StaticSqlSource) sqlSource);
            } else if (sqlSource instanceof RawSqlSource) {
                pageSqlSource = new PageRawSqlSource((RawSqlSource) sqlSource);
            } else if (sqlSource instanceof ProviderSqlSource) {
                pageSqlSource = new PageProviderSqlSource((ProviderSqlSource) sqlSource);
            } else if (sqlSource instanceof DynamicSqlSource) {
                pageSqlSource = new PageDynamicSqlSource((DynamicSqlSource) sqlSource);
            } else {
                throw new RuntimeException("无法处理该类型[" + sqlSource.getClass() + "]的SqlSource");
            }
            msObject.setValue("sqlSource", pageSqlSource);
            //由于count查询需要修改返回值,因此这里要创建一个Count查询的MS
            msCountMap.put(ms.getId(), MSUtils.newCountMappedStatement(ms));
        }
    

    parser的动态判断

    从sql链接中获取方言,例如mysql,通过mysql判断

        public static Parser newParser(Dialect dialect) {
            Parser parser = null;
            switch (dialect) {
                case mysql:
                case mariadb:
                case sqlite:
                    parser = new MysqlParser();
                    break;
                case oracle:
                    parser = new OracleParser();
                    break;
                case hsqldb:
                    parser = new HsqldbParser();
                    break;
                case sqlserver:
                    parser = new SqlServerParser();
                    break;
                case sqlserver2012:
                    parser = new SqlServer2012Dialect();
                    break;
                case db2:
                    parser = new Db2Parser();
                    break;
                case postgresql:
                    parser = new PostgreSQLParser();
                    break;
                case informix:
                    parser = new InformixParser();
                    break;
                case h2:
                    parser = new H2Parser();
                    break;
                default:
                    throw new RuntimeException("分页插件" + dialect + "方言错误!");
            }
            return parser;
        }
    

    参考

  • 相关阅读:
    金蝶问题:不能保存已审核的单据
    在代码中设置cxTreeList按多列排序
    日积月累篇:生产任务单
    sp_reset_connection
    日积月累篇:仓库流程
    使用FreeMarker生成Word文档 仅此而已
    ASP格式化时间日期(二)
    省市区三级联动连接数据库
    利用SQL语句进行添加、删除、修改字段,表与字段的基本操作,数据库备份等
    ASP截取字数(二)
  • 原文地址:https://www.cnblogs.com/seekwind/p/14325304.html
Copyright © 2011-2022 走看看