1.PagePlugin类
package com.tyro.plugin;
import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.Properties;
import javax.xml.bind.PropertyException;
import org.apache.ibatis.executor.ErrorContext;
import org.apache.ibatis.executor.ExecutorException;
import org.apache.ibatis.executor.statement.BaseStatementHandler;
import org.apache.ibatis.executor.statement.RoutingStatementHandler;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.ParameterMapping;
import org.apache.ibatis.mapping.ParameterMode;
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.reflection.MetaObject;
import org.apache.ibatis.reflection.property.PropertyTokenizer;
import org.apache.ibatis.scripting.xmltags.ForEachSqlNode;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.type.TypeHandler;
import org.apache.ibatis.type.TypeHandlerRegistry;
import com.tyro.util.ReflectHelper;
import com.tyro.util.Tools;
/**
*
* 类名称:PagePlugin.java
* 类描述:
* @author fuhang
* 作者单位:
* 联系方式:
* 创建时间:2014年7月1日
* @version 1.0
*/
@Intercepts({@Signature(type=StatementHandler.class,method="prepare",args={Connection.class})})
public class PagePlugin implements Interceptor {
private static String dialect = ""; //数据库方言
private static String pageSqlId = ""; //mapper.xml中需要拦截的ID(正则匹配)
public Object intercept(Invocation ivk) throws Throwable {
if(ivk.getTarget() instanceof RoutingStatementHandler){
RoutingStatementHandler statementHandler = (RoutingStatementHandler)ivk.getTarget();
BaseStatementHandler delegate = (BaseStatementHandler) ReflectHelper.getValueByFieldName(statementHandler, "delegate");
MappedStatement mappedStatement = (MappedStatement) ReflectHelper.getValueByFieldName(delegate, "mappedStatement");
if(mappedStatement.getId().matches(pageSqlId)){ //拦截需要分页的SQL
BoundSql boundSql = delegate.getBoundSql();
Object parameterObject = boundSql.getParameterObject();//分页SQL<select>中parameterType属性对应的实体参数,即Mapper接口中执行分页方法的参数,该参数不得为空
if(parameterObject==null){
throw new NullPointerException("parameterObject尚未实例化!");
}else{
Connection connection = (Connection) ivk.getArgs()[0];
String sql = boundSql.getSql();
//String countSql = "select count(0) from (" + sql+ ") as tmp_count"; //记录统计
String countSql = "select count(0) from (" + sql+ ") tmp_count"; //记录统计 == oracle 加 as 报错(SQL command not properly ended)
PreparedStatement countStmt = connection.prepareStatement(countSql);
BoundSql countBS = new BoundSql(mappedStatement.getConfiguration(),countSql,boundSql.getParameterMappings(),parameterObject);
setParameters(countStmt,mappedStatement,countBS,parameterObject);
ResultSet rs = countStmt.executeQuery();
int count = 0;
if (rs.next()) {
count = rs.getInt(1);
}
rs.close();
countStmt.close();
//System.out.println(count);
Page page = null;
if(parameterObject instanceof Page){ //参数就是Page实体
page = (Page) parameterObject;
page.setEntityOrField(true);
page.setTotalResult(count);
}else{ //参数为某个实体,该实体拥有Page属性
Field pageField = ReflectHelper.getFieldByFieldName(parameterObject,"page");
if(pageField!=null){
page = (Page) ReflectHelper.getValueByFieldName(parameterObject,"page");
if(page==null)
page = new Page();
page.setEntityOrField(false);
page.setTotalResult(count);
ReflectHelper.setValueByFieldName(parameterObject,"page", page); //通过反射,对实体对象设置分页对象
}else{
throw new NoSuchFieldException(parameterObject.getClass().getName()+"不存在 page 属性!");
}
}
String pageSql = generatePageSql(sql,page);
ReflectHelper.setValueByFieldName(boundSql, "sql", pageSql); //将分页sql语句反射回BoundSql.
}
}
}
return ivk.proceed();
}
/**
* 对SQL参数(?)设值,参考org.apache.ibatis.executor.parameter.DefaultParameterHandler
* @param ps
* @param mappedStatement
* @param boundSql
* @param parameterObject
* @throws SQLException
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
private void setParameters(PreparedStatement ps,MappedStatement mappedStatement,BoundSql boundSql,Object parameterObject) throws SQLException {
ErrorContext.instance().activity("setting parameters").object(mappedStatement.getParameterMap().getId());
List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
if (parameterMappings !&