packagespcommon.config;importorg.apache.ibatis.executor.Executor;import org.apache.ibatis.mapping.*;import org.apache.ibatis.plugin.*;importorg.apache.ibatis.session.ResultHandler;importorg.apache.ibatis.session.RowBounds;importorg.slf4j.Logger;importorg.slf4j.LoggerFactory;importjava.util.Properties;/*** 自定义 MyBatis 拦截器*/@Intercepts({@Signature(type= Executor.class, method = "query",
args= {MappedStatement.class, Object.class, RowBounds.class,ResultHandler.class})})public class MySqlInterceptor implementsInterceptor {private static final Logger logger= LoggerFactory.getLogger(MySqlInterceptor.class);/*** intercept 方法用来对拦截的sql进行具体的操作
*@paraminvocation
*@return*@throwsThrowable*/@Overridepublic Object intercept(Invocation invocation) throwsThrowable {
logger.info("执行intercept方法:{}", invocation.toString());
Object[] args=invocation.getArgs();
MappedStatement ms= (MappedStatement) args[0];
Object parameterObject= args[1];//id为执行的mapper方法的全路径名,如com.mapper.UserMapper
String id =ms.getId();//sql语句类型 select、delete、insert、update
String sqlCommandType =ms.getSqlCommandType().toString();//仅拦截 select 查询//if (!sqlCommandType.equals(SqlCommandType.SELECT.toString())) {//return invocation.proceed();//}
BoundSql boundSql=ms.getBoundSql(parameterObject);
String origSql=boundSql.getSql();
logger.info("原始SQL: {}", origSql);//组装新的 sql
String newSql = origSql + " limit 1";//重新new一个查询语句对象
BoundSql newBoundSql = newBoundSql(ms.getConfiguration(), newSql,
boundSql.getParameterMappings(), boundSql.getParameterObject());//把新的查询放到statement里
MappedStatement newMs = newMappedStatement(ms, newBoundSqlSqlSource(newBoundSql));for(ParameterMapping mapping : boundSql.getParameterMappings()) {
String prop=mapping.getProperty();if(boundSql.hasAdditionalParameter(prop)) {
newBoundSql.setAdditionalParameter(prop, boundSql.getAdditionalParameter(prop));
}
}
Object[] queryArgs=invocation.getArgs();
queryArgs[0] =newMs;
logger.info("改写的SQL: {}", newSql);returninvocation.proceed();
}/*** 定义一个内部辅助类,作用是包装 SQL*/
class BoundSqlSqlSource implementsSqlSource {privateBoundSql boundSql;publicBoundSqlSqlSource(BoundSql boundSql) {this.boundSql =boundSql;
}publicBoundSql getBoundSql(Object parameterObject) {returnboundSql;
}
}privateMappedStatement newMappedStatement (MappedStatement ms, SqlSource newSqlSource) {
MappedStatement.Builder builder= newMappedStatement.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 && ms.getKeyProperties().length > 0) {
builder.keyProperty(ms.getKeyProperties()[0]);
}
builder.timeout(ms.getTimeout());
builder.parameterMap(ms.getParameterMap());
builder.resultMaps(ms.getResultMaps());
builder.resultSetType(ms.getResultSetType());
builder.cache(ms.getCache());
builder.flushCacheRequired(ms.isFlushCacheRequired());
builder.useCache(ms.isUseCache());returnbuilder.build();
}
@OverridepublicObject plugin(Object target) {
logger.info("plugin方法:{}", target);if (target instanceofExecutor) {return Plugin.wrap(target, this);
}returntarget;
}
@Overridepublic voidsetProperties(Properties properties) {//获取属性//String value1 = properties.getProperty("prop1");
logger.info("properties方法:{}", properties.toString());
}
}