简要描述mybatis插件实现分页

来源:互联网 发布:php 视频断点续传 编辑:程序博客网 时间:2024/04/24 08:47

第一步:在mybatis配置文件中配置拦截器

<plugins>    <plugin interceptor="x.x.x.x.x.x.xxxInterceptor" /></plugins>

第二步:实现拦截器

package com.mg.background.common.persistence.interceptor;import java.util.Properties;import org.apache.commons.lang3.StringUtils;import org.apache.ibatis.executor.Executor;import org.apache.ibatis.mapping.BoundSql;import org.apache.ibatis.mapping.MappedStatement;import org.apache.ibatis.mapping.SqlSource;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.reflection.MetaObject;import org.apache.ibatis.session.ResultHandler;import org.apache.ibatis.session.RowBounds;import com.mg.background.common.persistence.Pages;import com.mg.background.common.persistence.utils.Reflections;//拦截器注解,拦截器必须实现Interceptor接口//AbstractInterceptor实现了Interceptor接口//@Intercepts的参数中为@Signature的数组,表示要拦截的类和类中要拦截的方法//args为这个方法需要的参数//MappedStatement.class 为一个节点对象 即<select/><insert/>之类//RowBounds.class分页对象 他的offset和limit属性表示要展示数据的范围//ResultHandler.class结果集映射@Intercepts({ @Signature(type = Executor.class, method = "query", args = { MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class }) })public class PaginationInterceptor extends AbstractInterceptor {    private static final long serialVersionUID = 4989671349466153547L;    @Override    public Object intercept(Invocation invocation) throws Throwable {    final MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];        Object parameter = invocation.getArgs()[1];        //boundSql为一条sql语句动态运行对象        //mappedStatement.getBoundSql(parameter);动态计算sql运行的条件        //即<if/>条件的计算,然后生成要运行的sql        BoundSql boundSql = mappedStatement.getBoundSql(parameter);        //得到入参类型        Object parameterObject = boundSql.getParameterObject();        //获取分页参数对象        Pages<Object> pages = null;        if (parameterObject != null) {            //利用反射机制访问对象属性            pages = convertParameter(parameterObject, pages);        }        //如果设置了分页对象,则进行分页        if (pages != null && pages.getPageSize() != -1) {            if (StringUtils.isBlank(boundSql.getSql())) {                return null;            }            String originalSql = boundSql.getSql().trim();            //得到总记录数            pages.setTotal(SQLHelper.getCount(originalSql, null, mappedStatement, parameterObject, boundSql, log));            //分页查询 本地化对象 修改数据库注意修改实现            String pageSql = SQLHelper.generatePageSql(originalSql, pages, DIALECT);            //                if (log.isDebugEnabled()) {            //                    log.debug("PAGE SQL:" + StringUtils.replace(pageSql, "\n", ""));            //                }            invocation.getArgs()[2] = new RowBounds(RowBounds.NO_ROW_OFFSET, RowBounds.NO_ROW_LIMIT);            BoundSql newBoundSql = new BoundSql(mappedStatement.getConfiguration(), pageSql, boundSql.getParameterMappings(), boundSql.getParameterObject());            //解决MyBatis 分页foreach 参数失效 start            if (Reflections.getFieldValue(boundSql, "metaParameters") != null) {                MetaObject mo = (MetaObject) Reflections.getFieldValue(boundSql, "metaParameters");                Reflections.setFieldValue(newBoundSql, "metaParameters", mo);            }            //解决MyBatis 分页foreach 参数失效 end            MappedStatement newMs = copyFromMappedStatement(mappedStatement, new BoundSqlSqlSource(newBoundSql));            invocation.getArgs()[0] = newMs;        }        //        }        return invocation.proceed();    }    //绑定插件    @Override    public Object plugin(Object target) {        //如果target有接口返回代理类,没有返回类本身        //如果代理类wrap方法会绑定一个拦截器,调用plugin的invoke方法        //将拦截的方法的参数初始化成一个Invocation对象 然后调用intercept方法        return Plugin.wrap(target, this);    }    //初始化拦截器时将配置文件中拦截器下配置的properties设置进来    @Override    public void setProperties(Properties properties) {        super.initProperties(properties);    }    private MappedStatement copyFromMappedStatement(MappedStatement ms, SqlSource newSqlSource) {        MappedStatement.Builder builder = new MappedStatement.Builder(ms.getConfiguration(), ms.getId(), newSqlSource, ms.getSqlCommandType());        builder.resource(ms.getResource());        builder.fetchSize(ms.getFetchSize());        builder.statementType(ms.getStatementType());        builder.keyGenerator(ms.getKeyGenerator());        if (ms.getKeyProperties() != null) {            for (String keyProperty : ms.getKeyProperties()) {                builder.keyProperty(keyProperty);            }        }        builder.timeout(ms.getTimeout());        builder.parameterMap(ms.getParameterMap());        builder.resultMaps(ms.getResultMaps());        builder.cache(ms.getCache());        return builder.build();    }    public static class BoundSqlSqlSource implements SqlSource {        BoundSql boundSql;        public BoundSqlSqlSource(BoundSql boundSql) {            this.boundSql = boundSql;        }        public BoundSql getBoundSql(Object parameterObject) {            return boundSql;        }    }}
0 0
原创粉丝点击