先说一下我们要做的事情:在sql执行前对sql进行动态修改。
那拦截器到底如何设计才能做到修改sql呢,就要说到sqlSession的四大对象executor, statementHandler, parameterHandler,resultHandler。对于这四大对象有很多文章解析。
自定义拦截器
@Signature声明要拦截的Executor对象中的query方法,如果方法不存在则会对该类所有方法进行拦截
/**
* @param invocation Mybatis将动态代理对象封装而成
* @return
* @throws Throwable
*/
@Override
public Object intercept(Invocation invocation) throws Throwable {
Object[] args = invocation.getArgs();
Executor executor = (Executor) invocation.getTarget();
MappedStatement mappedStatement = (MappedStatement) args[0];
Object parameter = args[1];
RowBounds rowBounds = (RowBounds) args[2];
ResultHandler resultHandler = (ResultHandler) args[3];
CacheKey cacheKey = null;
BoundSql boundSql = null;
if (4 == args.length) {
//拦截方法为4个参数时
boundSql = mappedStatement.getBoundSql(parameter);
cacheKey = executor.createCacheKey(mappedStatement, parameter, rowBounds, boundSql);
} else {
//拦截方法为6个参数时
cacheKey = (CacheKey) args[4];
boundSql = (BoundSql) args[5];
}
//逻辑判断,对sql做出处理等等
if (1==1) {
return executor.query(mappedStatement, parameter, RowBounds.DEFAULT, resultHandler, cacheKey, boundSql);
}
return executor.query(mappedStatement, parameter, rowBounds, resultHandler, cacheKey, boundSql);
}
注册拦截器
@Bean
public DataInterceptor myBatisInterceptor() {
return new DataInterceptor();
}
最终Mybatis会将拦截器放入一个List中按照顺序执行