您的位置:首页 > 其它

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);

}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: