拦截器实现分页

PageHelper.java

import java.util.List;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;
 
import org.apache.ibatis.binding.MapperMethod.ParamMap;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlSource;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.springframework.beans.BeanUtils;
 
import com.ai.sipom.sjfw.data.query.interfaces.vo.page.Page;
import com.ai.sipom.sjfw.data.query.server.util.SystemConfig;
import com.ai.sipom.sjfw.data.query.server.util.db.DbContextHolder;
 
/**
 * Mybatis - 通用分页拦截器
 *
 * @author 
 * @version 3.3.0
 * @createdate 2018年01月03日
 */
@SuppressWarnings({ "rawtypes""unchecked" })
@Intercepts(@Signature(type = Executor.class, method = "query", args = {
        MappedStatement.class, Object.class, RowBounds.class,
        ResultHandler.class }))
public class PageHelper implements Interceptor {
    // sql工具类
    private static SqlUtil SQLUTIL = null;
 
    /**
     * Mybatis拦截器方法
     *
     * @param invocation
     *            拦截器入参
     * @return 返回执行结果
     * @throws Throwable
     *             抛出异常
     */
    public Object intercept(Invocation invocation) throws Throwable {
        final Object[] args = invocation.getArgs();
 
        Page<?> page = null;
        int flag = 0;
        if (args[1instanceof ParamMap) {
            Set<Entry> entrySet = ((ParamMap) args[1]).entrySet();
            for (Entry entry : entrySet) {
                if (entry.getValue() instanceof Page) {
                    page = (Page<?>) entry.getValue();
                    break;
                }
            }
            flag = 1;
        else if (((MappedStatement) args[0]).getId().matches(".*Page$")) {
            Integer pageNum = (Integer) BeanUtils.getPropertyDescriptor(args[1].getClass(), "pageNum").getReadMethod().invoke(args[1], new Object[0]);
            Integer pageSize = (Integer) BeanUtils.getPropertyDescriptor(args[1].getClass(), "pageSize").getReadMethod().invoke(args[1], new Object[0]);
             
            page = new Page(pageNum, pageSize);
            flag = 2;
        }
         
        if (page != null) {
            // 忽略RowBounds-否则会进行Mybatis自带的内存分页
            args[2] = RowBounds.DEFAULT;
            // 获取原始的ms
            MappedStatement ms = (MappedStatement) args[0];
             
            SqlSource sqlSource = ms.getSqlSource();
            // 将参数中的MappedStatement替换为新的qs
            SQLUTIL.processCountMappedStatement(ms, sqlSource, args);
            // 查询总数
            Object totalResult = invocation.proceed();
            // 设置总数
            long totalCount = ((Integer) ((List) totalResult).get(0))
                    .longValue();
            page.setTotal(totalCount);
            long totalPage = totalCount / page.getPageSize() + ((totalCount % page.getPageSize() == 0) ? 0 1);  
            page.setPages(totalPage);  
            // 将参数中的MappedStatement替换为新的qs
            SQLUTIL.processPageMappedStatement(ms, sqlSource, page,
                    args);
            // 执行分页查询
            Object list = invocation.proceed();
            // 得到处理结果
            page.setList((List) list);
             
            //--------------------------
            if (flag == 2) {
                PageList pageList = new PageList();
                pageList.setPageNum(page.getPageNum());
                pageList.setPageSize(page.getPageSize());
                pageList.setStartRow(page.getStartRow());
                pageList.setEndRow(page.getEndRow());
                pageList.setPages(page.getPages());
                pageList.setTotal(page.getTotal());
                if (page.getList() != null) {
                    pageList.addAll(page.getList());
                    //pageList.setList(page.getList());
                }
                 
                return pageList;
            else if (flag == 1) {
                return list;
            }
        }
         
        // 返回结果
        return invocation.proceed();
    }
 
    /**
     * 只拦截Executor
     *
     * @param target
     * @return
     */
    public Object plugin(Object target) {
        if (target instanceof Executor) {
            return Plugin.wrap(target, this);
        else {
            return target;
        }
    }
 
    /**
     * 设置属性值
     *
     * @param p
     *            属性值
     */
    public void setProperties(Properties p) {
        String dialect = SystemConfig.getValue("jdbc" + DbContextHolder.getDBType() + ".dbtype");
        if (dialect == null) {
            dialect = "mysql"// 默认oracle数据库
        }
        SQLUTIL = new SqlUtil(dialect);
    }
}

SqlUtil.java

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.ibatis.builder.SqlSourceBuilder;
import org.apache.ibatis.builder.StaticSqlSource;
import org.apache.ibatis.builder.annotation.ProviderSqlSource;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.ParameterMapping;
import org.apache.ibatis.mapping.ResultMap;
import org.apache.ibatis.mapping.ResultMapping;
import org.apache.ibatis.mapping.SqlSource;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.factory.DefaultObjectFactory;
import org.apache.ibatis.reflection.factory.ObjectFactory;
import org.apache.ibatis.reflection.wrapper.DefaultObjectWrapperFactory;
import org.apache.ibatis.reflection.wrapper.ObjectWrapperFactory;
import org.apache.ibatis.scripting.xmltags.DynamicContext;
import org.apache.ibatis.scripting.xmltags.DynamicSqlSource;
import org.apache.ibatis.scripting.xmltags.MixedSqlNode;
import org.apache.ibatis.scripting.xmltags.SqlNode;
import org.apache.ibatis.session.Configuration;
import com.ai.sipom.sjfw.data.query.interfaces.vo.page.Page;
/**
 * Mybatis - sql工具,获取分页和count的MappedStatement,设置分页参数
 *
 * @author
 * @since 3.3.0
 * @createdate 2018年01月03日
 */
@SuppressWarnings({"rawtypes""unchecked"})
public class SqlUtil {
    private static final List<ResultMapping> EMPTY_RESULTMAPPING = new ArrayList<ResultMapping>(0);
    //分页的id后缀
    private static final String SUFFIX_PAGE = "_PageHelper";
    //count查询的id后缀
    private static final String SUFFIX_COUNT = SUFFIX_PAGE + "_Count";
    //第一个分页参数
    private static final String PAGEPARAMETER_FIRST = "First" + SUFFIX_PAGE;
    //第二个分页参数
    private static final String PAGEPARAMETER_SECOND = "Second" + SUFFIX_PAGE;
    private static final String PROVIDER_OBJECT = "_provider_object";
    private static final ObjectFactory DEFAULT_OBJECT_FACTORY = new DefaultObjectFactory();
    private static final ObjectWrapperFactory DEFAULT_OBJECT_WRAPPER_FACTORY = new DefaultObjectWrapperFactory();
    /**
     * 反射对象,增加对低版本Mybatis的支持
     *
     * @param object 反射对象
     * @return
     */
    private static MetaObject forObject(Object object) {
        return MetaObject.forObject(object, DEFAULT_OBJECT_FACTORY, DEFAULT_OBJECT_WRAPPER_FACTORY);
    }
    private SqlUtil.Parser sqlParser;
    //数据库方言 - 使用枚举限制数据库类型
    public enum Dialect {
        mysql, mariadb, sqlite, oracle, hsqldb, postgresql
    }
    /**
     * 构造方法
     *
     * @param strDialect
     */
    public SqlUtil(String strDialect) {
        if (strDialect == null || "".equals(strDialect)) {
            throw new IllegalArgumentException("Mybatis分页插件无法获取dialect参数!");
        }
        try {
            Dialect dialect = Dialect.valueOf(strDialect);
            String sqlParserClass = this.getClass().getPackage().getName() + ".SqlParser";
            try {
                //使用SqlParser必须引入jsqlparser-x.x.x.jar
                Class.forName("net.sf.jsqlparser.statement.select.Select");
                sqlParser = (Parser) Class.forName(sqlParserClass).getConstructor(Dialect.class).newInstance(dialect);
            catch (Exception e) {
                //找不到时,不用处理
            }
            if (sqlParser == null) {
                sqlParser = SimpleParser.newParser(dialect);
            }
        catch (IllegalArgumentException e) {
            String dialects = null;
            for (Dialect d : Dialect.values()) {
                if (dialects == null) {
                    dialects = d.toString();
                else {
                    dialects += "," + d;
                }
            }
            throw new IllegalArgumentException("Mybatis分页插件dialect参数值错误,可选值为[" + dialects + "]");
        }
    }
    /**
     * 设置分页参数
     *
     * @param parameterObject
     * @param page
     * @return
     */
    public Map setPageParameter(MappedStatement ms, Object parameterObject, Page page) {
        BoundSql boundSql = ms.getBoundSql(parameterObject);
        return sqlParser.setPageParameter(ms, parameterObject, boundSql, page);
    }
    /**
     * 处理count查询的MappedStatement
     *
     * @param ms
     * @param sqlSource
     * @param args
     */
    public void processCountMappedStatement(MappedStatement ms, SqlSource sqlSource, Object[] args) {
        args[0] = getMappedStatement(ms, sqlSource, args[1], SUFFIX_COUNT);
    }
    /**
     * 处理分页查询的MappedStatement
     *
     * @param ms
     * @param sqlSource
     * @param page
     * @param args
     */
    public void processPageMappedStatement(MappedStatement ms, SqlSource sqlSource, Page page, Object[] args) {
        args[0] = getMappedStatement(ms, sqlSource, args[1], SUFFIX_PAGE);
        //处理入参
        args[1] = setPageParameter((MappedStatement) args[0], args[1], page);
    }
    /**
     * 处理SQL
     */
    public static interface Parser {
        void isSupportedSql(String sql);
        String getCountSql(String sql);
        String getPageSql(String sql);
        Map setPageParameter(MappedStatement ms, Object parameterObject, BoundSql boundSql, Page page);
    }
    public static abstract class SimpleParser implements Parser {
        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 postgresql:
                default:
                    parser = new PostgreSQLParser();
            }
            return parser;
        }
        public void isSupportedSql(String sql) {
            if (sql.trim().toUpperCase().endsWith("FOR UPDATE")) {
                throw new RuntimeException("分页插件不支持包含for update的sql");
            }
        }
        /**
         * 获取总数sql - 如果要支持其他数据库,修改这里就可以
         *
         * @param sql 原查询sql
         * @return 返回count查询sql
         */
        public String getCountSql(final String sql) {
            isSupportedSql(sql);
            StringBuilder stringBuilder = new StringBuilder(sql.length() + 40);
            stringBuilder.append("select count(*) from (");
            stringBuilder.append(sql);
            stringBuilder.append(") tmp_count");
            return stringBuilder.toString();
        }
        /**
         * 获取分页sql - 如果要支持其他数据库,修改这里就可以
         *
         * @param sql 原查询sql
         * @return 返回分页sql
         */
        public abstract String getPageSql(String sql);
        public Map setPageParameter(MappedStatement ms, Object parameterObject, BoundSql boundSql, Page page) {
            Map paramMap = null;
            if (parameterObject == null) {
                paramMap = new HashMap();
            else if (parameterObject instanceof Map) {
                paramMap = (Map) parameterObject;
            else {
                paramMap = new HashMap();
                //动态sql时的判断条件不会出现在ParameterMapping中,但是必须有,所以这里需要收集所有的getter属性
                //TypeHandlerRegistry可以直接处理的会作为一个直接使用的对象进行处理
                boolean hasTypeHandler = ms.getConfiguration().getTypeHandlerRegistry().hasTypeHandler(parameterObject.getClass());
                MetaObject metaObject = forObject(parameterObject);
                //需要针对注解形式的MyProviderSqlSource保存原值
                if (ms.getSqlSource() instanceof MyProviderSqlSource) {
                    paramMap.put(PROVIDER_OBJECT, parameterObject);
                }
                if (!hasTypeHandler) {
                    for (String name : metaObject.getGetterNames()) {
                        paramMap.put(name, metaObject.getValue(name));
                    }
                }
                //下面这段方法,主要解决一个常见类型的参数时的问题
                if (boundSql.getParameterMappings() != null && boundSql.getParameterMappings().size() > 0) {
                    for (ParameterMapping parameterMapping : boundSql.getParameterMappings()) {
                        String name = parameterMapping.getProperty();
                        if (!name.equals(PAGEPARAMETER_FIRST)
                                && !name.equals(PAGEPARAMETER_SECOND)
                                && paramMap.get(name) == null) {
                            if (hasTypeHandler
                                    || parameterMapping.getJavaType().equals(parameterObject.getClass())) {
                                paramMap.put(name, parameterObject);
                            else {
                                paramMap.put(name, metaObject.getValue(name));
                            }
                        }
                    }
                }
            }
            return paramMap;
        }
    }
    //Mysql
    private static class MysqlParser extends SimpleParser {
        @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 setPageParameter(MappedStatement ms, Object parameterObject, BoundSql boundSql, Page page) {
            Map paramMap = super.setPageParameter(ms, parameterObject, boundSql, page);
            paramMap.put(PAGEPARAMETER_FIRST, page.getStartRow());
            paramMap.put(PAGEPARAMETER_SECOND, page.getPageSize());
            return paramMap;
        }
    }
    //Oracle
    private static class OracleParser extends SimpleParser {
        @Override
        public String getPageSql(String sql) {
            StringBuilder sqlBuilder = new StringBuilder(sql.length() + 120);
            sqlBuilder.append("select * from ( select tmp_page.*, rownum row_id from ( ");
            sqlBuilder.append(sql);
            sqlBuilder.append(" ) tmp_page where rownum <= ? ) where row_id > ?");
            return sqlBuilder.toString();
        }
        @Override
        public Map setPageParameter(MappedStatement ms, Object parameterObject, BoundSql boundSql, Page page) {
            Map paramMap = super.setPageParameter(ms, parameterObject, boundSql, page);
            paramMap.put(PAGEPARAMETER_FIRST, page.getEndRow());
            paramMap.put(PAGEPARAMETER_SECOND, page.getStartRow());
            return paramMap;
        }
    }
    //Oracle
    private static class HsqldbParser extends SimpleParser {
        @Override
        public String getPageSql(String sql) {
            StringBuilder sqlBuilder = new StringBuilder(sql.length() + 20);
            sqlBuilder.append(sql);
            sqlBuilder.append(" limit ? offset ?");
            return sqlBuilder.toString();
        }
        @Override
        public Map setPageParameter(MappedStatement ms, Object parameterObject, BoundSql boundSql, Page page) {
            Map paramMap = super.setPageParameter(ms, parameterObject, boundSql, page);
            paramMap.put(PAGEPARAMETER_FIRST, page.getPageSize());
            paramMap.put(PAGEPARAMETER_SECOND, page.getStartRow());
            return paramMap;
        }
    }
    //PostgreSQL
    private static class PostgreSQLParser extends SimpleParser {
        @Override
        public String getPageSql(String sql) {
            StringBuilder sqlBuilder = new StringBuilder(sql.length() + 14);
            sqlBuilder.append(sql);
            sqlBuilder.append(" limit ? offset ?");
            return sqlBuilder.toString();
        }
        @Override
        public Map setPageParameter(MappedStatement ms, Object parameterObject, BoundSql boundSql, Page page) {
            Map paramMap = super.setPageParameter(ms, parameterObject, boundSql, page);
            paramMap.put(PAGEPARAMETER_FIRST, page.getPageSize());
            paramMap.put(PAGEPARAMETER_SECOND, page.getStartRow());
            return paramMap;
        }
    }
    /**
     * 自定义动态SqlSource
     */
    private class MyDynamicSqlSource implements SqlSource {
        private Configuration configuration;
        private SqlNode rootSqlNode;
        /**
         * 用于区分动态的count查询或分页查询
         */
        private Boolean count;
        public MyDynamicSqlSource(Configuration configuration, SqlNode rootSqlNode, Boolean count) {
            this.configuration = configuration;
            this.rootSqlNode = rootSqlNode;
            this.count = count;
        }
        public BoundSql getBoundSql(Object parameterObject) {
            DynamicContext context = new DynamicContext(configuration, parameterObject);
            rootSqlNode.apply(context);
            SqlSourceBuilder sqlSourceParser = new SqlSourceBuilder(configuration);
            Class<?> parameterType = parameterObject == null ? Object.class : parameterObject.getClass();
            SqlSource sqlSource = sqlSourceParser.parse(context.getSql(), parameterType, context.getBindings());
            if (count) {
                sqlSource = getCountSqlSource(configuration, sqlSource, parameterObject);
            else {
                sqlSource = getPageSqlSource(configuration, sqlSource, parameterObject);
            }
            BoundSql boundSql = sqlSource.getBoundSql(parameterObject);
            //设置条件参数
            for (Map.Entry<String, Object> entry : context.getBindings().entrySet()) {
                boundSql.setAdditionalParameter(entry.getKey(), entry.getValue());
            }
            return boundSql;
        }
    }
    /**
     * 自定义ProviderSqlSource,代理方法
     */
    private class MyProviderSqlSource implements SqlSource {
        private Configuration configuration;
        private ProviderSqlSource providerSqlSource;
        /**
         * 用于区分动态的count查询或分页查询
         */
        private Boolean count;
        private MyProviderSqlSource(Configuration configuration, ProviderSqlSource providerSqlSource, Boolean count) {
            this.configuration = configuration;
            this.providerSqlSource = providerSqlSource;
            this.count = count;
        }
        @Override
        public BoundSql getBoundSql(Object parameterObject) {
            BoundSql boundSql = null;
            if (parameterObject instanceof Map && ((Map) parameterObject).containsKey(PROVIDER_OBJECT)) {
                boundSql = providerSqlSource.getBoundSql(((Map) parameterObject).get(PROVIDER_OBJECT));
            else {
                boundSql = providerSqlSource.getBoundSql(parameterObject);
            }
            if (count) {
                return new BoundSql(
                        configuration,
                        sqlParser.getCountSql(boundSql.getSql()),
                        boundSql.getParameterMappings(),
                        parameterObject);
            else {
                return new BoundSql(
                        configuration,
                        sqlParser.getPageSql(boundSql.getSql()),
                        getPageParameterMapping(configuration, boundSql),
                        parameterObject);
            }
        }
    }
    /**
     * 获取ms - 在这里对新建的ms做了缓存,第一次新增,后面都会使用缓存值
     *
     * @param ms
     * @param sqlSource
     * @param suffix
     * @return
     */
    private MappedStatement getMappedStatement(MappedStatement ms, SqlSource sqlSource, Object parameterObject, String suffix) {
        MappedStatement qs = null;
        try {
            qs = ms.getConfiguration().getMappedStatement(ms.getId() + suffix);
        catch (Exception e) {
            //ignore
        }
        if (qs == null) {
            //创建一个新的MappedStatement
            qs = newMappedStatement(ms, getsqlSource(ms, sqlSource, parameterObject, suffix), suffix);
            try {
                ms.getConfiguration().addMappedStatement(qs);
            catch (Exception e) {
                //ignore
            }
        }
        return qs;
    }
    /**
     * 新建count查询和分页查询的MappedStatement
     *
     * @param ms
     * @param sqlSource
     * @param suffix
     * @return
     */
    private MappedStatement newMappedStatement(MappedStatement ms, SqlSource sqlSource, String suffix) {
        String id = ms.getId() + suffix;
        MappedStatement.Builder builder = new MappedStatement.Builder(ms.getConfiguration(), id, sqlSource, 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());
        if (suffix == SUFFIX_PAGE) {
            builder.resultMaps(ms.getResultMaps());
        else {
            //count查询返回值int
            List<ResultMap> resultMaps = new ArrayList<ResultMap>();
            ResultMap resultMap = new ResultMap.Builder(ms.getConfiguration(), id, 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
     *
     * @param ms
     * @return
     */
    public boolean isDynamic(MappedStatement ms) {
        return ms.getSqlSource() instanceof DynamicSqlSource;
    }
    /**
     * 获取新的sqlSource
     *
     * @param ms
     * @param sqlSource
     * @param parameterObject
     * @param suffix
     * @return
     */
    private SqlSource getsqlSource(MappedStatement ms, SqlSource sqlSource, Object parameterObject, String suffix) {
        //1. 从XMLLanguageDriver.java和XMLScriptBuilder.java可以看出只有两种SqlSource
        //2. 增加注解情况的ProviderSqlSource
        //3. 对于RawSqlSource需要进一步测试完善
        //如果是动态sql
        if (isDynamic(ms)) {
            MetaObject msObject = forObject(ms);
            SqlNode sqlNode = (SqlNode) msObject.getValue("sqlSource.rootSqlNode");
            MixedSqlNode mixedSqlNode = null;
            if (sqlNode instanceof MixedSqlNode) {
                mixedSqlNode = (MixedSqlNode) sqlNode;
            else {
                List<SqlNode> contents = new ArrayList<SqlNode>(1);
                contents.add(sqlNode);
                mixedSqlNode = new MixedSqlNode(contents);
            }
            return new MyDynamicSqlSource(ms.getConfiguration(), mixedSqlNode, suffix == SUFFIX_COUNT);
        else if (sqlSource instanceof ProviderSqlSource) {
            return new MyProviderSqlSource(ms.getConfiguration(), (ProviderSqlSource) sqlSource, suffix == SUFFIX_COUNT);
        }
        //如果是静态分页sql
        else if (suffix == SUFFIX_PAGE) {
            //改为分页sql
            return getPageSqlSource(ms.getConfiguration(), sqlSource, parameterObject);
        }
        //如果是静态count-sql
        else {
            return getCountSqlSource(ms.getConfiguration(), sqlSource, parameterObject);
        }
    }
    /**
     * 增加分页参数映射
     *
     * @param configuration
     * @param boundSql
     * @return
     */
    private List<ParameterMapping> getPageParameterMapping(Configuration configuration, BoundSql boundSql) {
        List<ParameterMapping> newParameterMappings = new ArrayList<ParameterMapping>();
        newParameterMappings.addAll(boundSql.getParameterMappings());
        newParameterMappings.add(new ParameterMapping.Builder(configuration, PAGEPARAMETER_FIRST, Integer.class).build());
        newParameterMappings.add(new ParameterMapping.Builder(configuration, PAGEPARAMETER_SECOND, Integer.class).build());
        return newParameterMappings;
    }
    /**
     * 获取分页的sqlSource
     *
     * @param configuration
     * @param sqlSource
     * @return
     */
    private SqlSource getPageSqlSource(Configuration configuration, SqlSource sqlSource, Object parameterObject) {
        BoundSql boundSql = sqlSource.getBoundSql(parameterObject);
        return new StaticSqlSource(configuration, sqlParser.getPageSql(boundSql.getSql()), getPageParameterMapping(configuration, boundSql));
    }
    /**
     * 获取count的sqlSource
     *
     * @param sqlSource
     * @return
     */
    private SqlSource getCountSqlSource(Configuration configuration, SqlSource sqlSource, Object parameterObject) {
        BoundSql boundSql = sqlSource.getBoundSql(parameterObject);
        return new StaticSqlSource(configuration, sqlParser.getCountSql(boundSql.getSql()), boundSql.getParameterMappings());
    }
    /**
     * 测试[控制台输出]count和分页sql
     *
     * @param dialet      数据库类型
     * @param originalSql 原sql
     */
    public static void testSql(String dialet, String originalSql) {
        SqlUtil sqlUtil = new SqlUtil(dialet);
        String countSql = sqlUtil.sqlParser.getCountSql(originalSql);
        System.out.println(countSql);
        String pageSql = sqlUtil.sqlParser.getPageSql(originalSql);
        System.out.println(pageSql);
    }
}

PageList.java

import java.util.ArrayList;
/**
 * 分页
 
 * @author
 *
 * @param <E>
 * @createdate 2018年01月03日
 */
public class PageList<E> extends ArrayList<E> {
     
    /**
     
     */
    private static final long serialVersionUID = 1L;
    private Integer pageNum;
    private Integer pageSize;
    private Integer startRow;
    private Integer endRow;
    private Long total;
    private Long pages;
    public PageList() {
    }
    public PageList(Integer pageNum, Integer pageSize) {
        this.pageNum = pageNum;
        this.pageSize = pageSize;
        this.startRow = pageNum > 0 ? (pageNum - 1) * pageSize : 0;
        this.endRow = pageNum * pageSize;
    }
    public Long getPages() {
        return pages;
    }
    public void setPages(Long pages) {
        this.pages = pages;
    }
    public Integer getEndRow() {
        return endRow;
    }
    public void setEndRow(Integer endRow) {
        this.endRow = endRow;
    }
    public Integer getPageNum() {
        return pageNum;
    }
    public void setPageNum(Integer pageNum) {
        this.pageNum = pageNum;
    }
    public Integer getPageSize() {
        return pageSize;
    }
    public void setPageSize(Integer pageSize) {
        this.pageSize = pageSize;
    }
    public Integer getStartRow() {
        return startRow;
    }
    public void setStartRow(Integer startRow) {
        this.startRow = startRow;
    }
    public Long getTotal() {
        return total;
    }
    public void setTotal(Long total) {
        this.total = total;
    }
    @Override
    public String toString() {
        return "Page{" +
                "pageNum=" + pageNum +
                ", pageSize=" + pageSize +
                ", startRow=" + startRow +
                ", endRow=" + endRow +
                ", total=" + total +
                ", pages=" + pages +
                '}';
    }
}

Page.java

import java.io.Serializable;
import java.util.List;
/**
 * @author
 * @createdate 2018年01月03日
 * */
public class Page<T> implements Serializable {
   private static final long serialVersionUID = 1L;
   private Integer pageNum;
   private Integer pageSize;
   private Integer startRow;
   private Integer endRow;
   private Long total;
   private Long pages;
   private List<T> list;
   public Page() {
   }
   public Page(Integer pageNum, Integer pageSize) {
      this.pageNum = pageNum;
      this.pageSize = pageSize;
      this.startRow = Integer.valueOf(pageNum.intValue() > 0?(pageNum.intValue() - 1) * pageSize.intValue():0);
      this.endRow = Integer.valueOf(pageNum.intValue() * pageSize.intValue());
   }
   public List<T> getList() {
      return this.list;
   }
   public void setList(List<T> list) {
      this.list = list;
   }
   public Long getPages() {
      return this.pages;
   }
   public void setPages(Long pages) {
      this.pages = pages;
   }
   public Integer getEndRow() {
      return this.endRow;
   }
   public void setEndRow(Integer endRow) {
      this.endRow = endRow;
   }
   public Integer getPageNum() {
      return this.pageNum;
   }
   public void setPageNum(Integer pageNum) {
      this.pageNum = pageNum;
   }
   public Integer getPageSize() {
      return this.pageSize;
   }
   public void setPageSize(Integer pageSize) {
      this.pageSize = pageSize;
   }
   public Integer getStartRow() {
      return this.startRow;
   }
   public void setStartRow(Integer startRow) {
      this.startRow = startRow;
   }
   public Long getTotal() {
      return this.total;
   }
   public void setTotal(Long total) {
      this.total = total;
   }
   public String toString() {
      return "Page{pageNum=" this.pageNum + ", pageSize=" this.pageSize + ", startRow=" this.startRow + ", endRow=" this.endRow + ", total=" this.total + ", pages=" this.pages + '}';
   }
}

DbContextHolder.java

/**
 * Title: AIDP_SMARTOS <br>
 * Description: 数据源变量存储处,这里是个线程安全的ThreadLocal的包装<br>
 * Date: 2018年01月03日 <br>
 * Copyright (c) 2018 AIDP <br>
 * @author 
 */
public class DbContextHolder {
    private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();
     
    public static void setDBType(String dbType) {
        contextHolder.set(dbType);
    }
     
    public static String getDBType() {
        return StringKit.isBlank(contextHolder.get()) ? "" : contextHolder.get();
    }
     
    public static void clearDBType() {
        contextHolder.remove();
    }
}

StringKit.java

/**
 * @author
 * @createdate 2018年01月03日
 * */
public class StringKit {
   public static String javaToDbFieldName(String name) {
      StringBuilder result = new StringBuilder();
      if(notBlank(name) && name.indexOf("_") < 0) {
         result.append(name.substring(01).toLowerCase());
         for(int i = 1; i < name.length(); ++i) {
            String s = name.substring(i, i + 1);
            if(s.equals(s.toUpperCase()) && !Character.isDigit(s.charAt(0))) {
               result.append("_");
            }
            result.append(s.toLowerCase());
         }
         return result.toString();
      else {
         name = notBlank(name)?name:"";
         return name;
      }
   }
   public static String dbToJavaFieldName(String name) {
      StringBuilder result = new StringBuilder();
      if(notBlank(name)) {
         name = name.toLowerCase();
         for(int i = 0; i < name.length(); ++i) {
            String s = name.substring(i, i + 1);
            if(s.equals("_") && i < name.length() - 1) {
               ++i;
               s = name.substring(i, i + 1);
               result.append(s.toUpperCase());
            else {
               result.append(s);
            }
         }
      }
      return result.toString();
   }
   public static String firstCharToLowerCase(String str) {
      char firstChar = str.charAt(0);
      if(firstChar >= 65 && firstChar <= 90) {
         char[] arr = str.toCharArray();
         arr[0] = (char)(arr[0] + 32);
         return new String(arr);
      else {
         return str;
      }
   }
   public static String firstCharToUpperCase(String str) {
      char firstChar = str.charAt(0);
      if(firstChar >= 97 && firstChar <= 122) {
         char[] arr = str.toCharArray();
         arr[0] = (char)(arr[0] - 32);
         return new String(arr);
      else {
         return str;
      }
   }
   public static boolean isBlank(String str) {
      return str == null || "".equals(str.trim());
   }
   public static boolean notBlank(String str) {
      return str != null && !"".equals(str.trim());
   }
   public static boolean notBlank(String... strings) {
      if(strings == null) {
         return false;
      else {
         String[] arr$ = strings;
         int len$ = strings.length;
         for(int i$ = 0; i$ < len$; ++i$) {
            String str = arr$[i$];
            if(str == null || "".equals(str.trim())) {
               return false;
            }
         }
         return true;
      }
   }
   public static boolean notNull(Object... paras) {
      if(paras == null) {
         return false;
      else {
         Object[] arr$ = paras;
         int len$ = paras.length;
         for(int i$ = 0; i$ < len$; ++i$) {
            Object obj = arr$[i$];
            if(obj == null) {
               return false;
            }
         }
         return true;
      }
   }
   public static String escapeNull(String str) {
      return notBlank(str)?str:"";
   }
   public static String addSlash(String path) {
      return path == null?"/":(path.startsWith("/")?path:"/" + path);
   }
}

BaseSvcUtil.java

import java.util.ArrayList;
/**
 * 后台服务统一工具类
 * @author 
 * @since 2018年01月03日
 * @history V0.1
 */
public class BaseSvcUtil {
     
    public static <T> Page<T> getPage(PageList<T> pageList) {
        Page<T> page = new Page<T>();
         
        page.setPageNum(pageList.getPageNum());
        page.setPageSize(pageList.getPageSize());
        page.setStartRow(pageList.getStartRow());
        page.setEndRow(pageList.getEndRow());
        page.setPages(pageList.getPages());
        page.setTotal(pageList.getTotal());
        page.setList(new ArrayList<T>(pageList));
        //page.setList(pageList.getList());
         
        return page;
    }
}
eg:
public Page<PatentVO> queryByNamePage(PatentVO patentVO) {
    PageList<PatentVO> pageList = xxxVOMapper.queryByNamePage(patentVO);
    if(pageList!=null)
        return BaseSvcUtil.getPage(pageList);
    else
        return null;
}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值