mybatis 分页插件
2017-12-07 11:11
148 查看
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); } }
相关文章推荐
- 2017.12.25 Mybatis物理分页插件PageHelper的使用(二)
- Mybatis拦截器介绍及分页插件
- Mybatis分页插件
- MyBatis分页插件PageHelper的使用
- Mybatis拦截器介绍及分页插件
- Mybatis分页插件 - PageHelper的使用
- Mybatis分页插件-PageHepler的使用
- mybatis分页插件pagehelper
- MyBatis分页插件PageHelper的使用
- easyui 分页 + mybatis 分页插件 PageHelper 完成分页显示功能(SpringMVC + mybatis 框架)
- MyBatis Generator实现分页插件
- MyBatis Generator实现分页插件
- Mybatis 数据库物理分页插件 PageHelper
- Mybatis插件原理分析(三)分页插件
- 关于mybatis中对mysql和Oracle数据库分页插件的使用
- mybatis分页插件PagePlugin
- mybatis分页插件使用(spring4.1.4结合mybatis3.2.8)
- Mybatis的分页插件
- mybatis分页插件pagehelper
- Mybatis的分页插件PageHelper