mybatis 分页插件

来源:互联网 发布:java api接口签名验证 编辑:程序博客网 时间:2024/06/05 07:25
package org.gjl.interceptor;import org.apache.ibatis.executor.parameter.ParameterHandler;import org.apache.ibatis.executor.statement.StatementHandler;import org.apache.ibatis.io.Resources;import org.apache.ibatis.mapping.BoundSql;import org.apache.ibatis.mapping.MappedStatement;import org.apache.ibatis.plugin.*;import org.apache.ibatis.reflection.MetaObject;import org.apache.ibatis.reflection.SystemMetaObject;import org.apache.ibatis.scripting.defaults.DefaultParameterHandler;import org.apache.ibatis.session.Configuration;import org.gjl.vo.Parameters;import java.beans.IntrospectionException;import java.beans.PropertyDescriptor;import java.lang.reflect.Field;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;import java.util.Iterator;import java.util.Map;import java.util.Properties;import java.util.Set;/** * @Author GJL * @Desription * @Date 2017/12/6 * @Modified By: **/@Intercepts({@Signature(type = StatementHandler.class,method = "prepare",args = {Connection.class,Integer.class})})public class MyInterceptor implements Interceptor{    private Integer defaultPage;    private Integer defaultPageSize;    private Boolean defaultUseFlag;    private Boolean defaultCheckFlag;    private Boolean defaultCleanOyderBy;    public Object intercept(Invocation invocation) throws Throwable {        StatementHandler stmtHandler = (StatementHandler)getUnproxyObject(invocation.getTarget());        MetaObject metaStatementHandler =  SystemMetaObject.forObject(stmtHandler);        String sql = (String)metaStatementHandler.getValue("delegate.boundSql.sql");        //mappedStatement 保存了一个映射器节点的内容 包含 我们配置的sql id 缓存信息 jdbcType javaType ResultType        // ParameterType等重要内容 还有SqlSource 接口 该接口有多中实现 ,getBoundSql(ParameterObject)是他的方法。        MappedStatement mappedStatement = (MappedStatement) metaStatementHandler.getValue("delegate.mappedStatement");        if(!checkSeleck(sql)){            invocation.proceed();        }        BoundSql boundSql = (BoundSql) metaStatementHandler.getValue("delegate.boundSql");        Object parameterObject = boundSql.getParameterObject();        //获取到参数       Parameters pageParams = getPageParamsFromParamObj(parameterObject);       if(pageParams == null){           return invocation.proceed();       }       //若不使用插件 则直接返回       Boolean useFlag = pageParams.getUseFlag() == null?this.defaultUseFlag:pageParams.getUseFlag();       if(!useFlag){           return invocation.proceed();       }       //获取相关配置的参数        Integer currentPage = pageParams.getCurrentPage() == null?this.defaultPage:pageParams.getCurrentPage();       Integer pageSize = pageParams.getPageSize() == null ?this.defaultPageSize:pageParams.getPageSize();       Boolean cleanOrderBy = pageParams.getCleanOrderBy() == null ?this.defaultCleanOyderBy:pageParams.getCleanOrderBy();       Boolean checkFlag = pageParams.getCheckFlag() == null ?this.defaultCheckFlag:pageParams.getCheckFlag();       //计算总条数        int total = getTotal(invocation,metaStatementHandler,boundSql,cleanOrderBy);        //回填总条数到页面参数        pageParams.setTotal(total);        //计算总页数        int totalPage = total%pageSize == 0 ? total/pageSize : total/pageSize+1;        //回填总页数到分页参数        pageParams.setTotalPage(totalPage);        //检查当前页码的有效性        checkPage(checkFlag,currentPage,totalPage);        //修改sql        return prepareSQl(invocation,metaStatementHandler,boundSql,currentPage,pageSize);    }    private Object prepareSQl(Invocation invocation, MetaObject metaStatementHandler, BoundSql boundSql, Integer currentPage, Integer pageSize) throws InvocationTargetException, IllegalAccessException, SQLException {            String sql = boundSql.getSql();            String newSql = "select * from ("+sql+") $_paging_table  limit ?,?";            metaStatementHandler.setValue("delegate.boundSql.sql",newSql);             Object statementObj = invocation.proceed();             this.preparePageDataParams((PreparedStatement)statementObj,currentPage,pageSize);             return statementObj;    }    private void preparePageDataParams(PreparedStatement preparedStatement, Integer currentPage, Integer pageSize) throws SQLException {        int idx = preparedStatement.getParameterMetaData().getParameterCount();        preparedStatement.setInt(idx-1,(currentPage-1)*pageSize);        preparedStatement.setInt(idx,pageSize);    }    private void checkPage(Boolean checkFlag, Integer currentPage, int totalPage) throws Exception {        if(checkFlag){            if(currentPage>totalPage){                throw new Exception("查询失败【"+currentPage+"】大于总页数"+"【"+totalPage+"】!!");            }        }    }    private int getTotal(Invocation ivt, MetaObject metaStatementHandler, BoundSql boundSql, Boolean cleanOrderBy) {        //获取当前的MappedStatement       MappedStatement mappedStatement = (MappedStatement) metaStatementHandler.getValue("delegate.mappedStatement");       //配置对象        Configuration cfg = mappedStatement.getConfiguration();        //当前需要执行的sql        String sql = (String)metaStatementHandler.getValue("delegate.boundSql.sql");        //去掉最后的clearOrderBy        sql = cleanOrderByForSql(sql);        //改写为统计总数的sql语句        String countSql = "select count(*) as total from ("+sql+") $_paging";        Connection connection = (Connection) ivt.getArgs()[0];        PreparedStatement ps = null;        int total =0;        try {            ps = connection.prepareStatement(countSql);            BoundSql countBoundSql = new BoundSql(cfg,countSql,boundSql.getParameterMappings(),boundSql.getParameterObject());            ParameterHandler handler = new DefaultParameterHandler(mappedStatement,boundSql.getParameterObject(),countBoundSql);            handler.setParameters(ps);            ResultSet rs = ps.executeQuery();            while(rs.next()){                 total = rs.getInt("total");            }        } catch (SQLException e) {            e.printStackTrace();        }finally {            if(ps !=null){                try {                    ps.close();                } catch (SQLException e) {                    e.printStackTrace();                }            }        }        return total;    }    private String cleanOrderByForSql(String sql) {        StringBuilder sb = new StringBuilder(sql);        String newSql  = sql.toLowerCase();        int index = newSql.lastIndexOf("order");        if(index == -1){            return sql;        }        return sb.substring(0,index);    }    private Parameters getPageParamsFromParamObj(Object parameterObject) {        Parameters parameters = null;        if(parameterObject == null){            return null;        }        if(parameterObject instanceof Map){            Map<String,Object> paramMap = (Map<String,Object>) parameterObject;            Set<String> keySet = paramMap.keySet();            Iterator<String> iterator = keySet.iterator();            while(iterator.hasNext()){                String key = iterator.next();                Object value = paramMap.get(key);                if(value instanceof Parameters){                    return (Parameters) value;                }            }        }else if(parameterObject instanceof Parameters){            return (Parameters)parameterObject;        }else{            Field[] fields = parameterObject.getClass().getDeclaredFields();            for(Field field :fields){                if(field.getType() == Parameters.class){                    try {                        PropertyDescriptor pd = new PropertyDescriptor(field.getName(),parameterObject.getClass());                      Method method =   pd.getReadMethod();                      return (Parameters) method.invoke(parameterObject);                    } catch (IntrospectionException e) {                        e.printStackTrace();                    } catch (IllegalAccessException e) {                        e.printStackTrace();                    } catch (InvocationTargetException e) {                        e.printStackTrace();                    }                }            }        }        return parameters;    }    private boolean checkSeleck(String sql) {        String trimSql = sql.trim();        int  index = trimSql.indexOf("select");        return index == 0;    }    private Object getUnproxyObject(Object target) {        MetaObject metaObject = SystemMetaObject.forObject(target);        Object object = null;        while(metaObject.hasGetter("h")){            object = metaObject.getValue("h");            metaObject = SystemMetaObject.forObject(object);        }        if(object == null){            return target;        }        return object;    }    public Object plugin(Object target) {        return Plugin.wrap(target,this);    }    //设置插件配置参数    public void setProperties(Properties properties) {        String strDefaultPage =  properties.getProperty("default.page","1");        String strDefaultPageSize = properties.getProperty("default.pageSize","50");        String strDefaultUseFlag = properties.getProperty("default.useFlag","false");        String strDefaultCheckFlag = properties.getProperty("default.checkFlag","false");        String strDefaultCleanOrderBy = properties.getProperty("default.cleanOrderBy","false");        this.defaultPage = Integer.parseInt(strDefaultPage);        this.defaultPageSize = Integer.parseInt(strDefaultPageSize);        this.defaultCheckFlag = Boolean.parseBoolean(strDefaultCheckFlag);        this.defaultUseFlag = Boolean.parseBoolean(strDefaultUseFlag);        this.defaultCleanOyderBy = Boolean.parseBoolean(strDefaultCleanOrderBy);    }}
原创粉丝点击