拦截器介绍
mybatis提供了@Intercepts注解允许开发者对mybatis的执行器Executor进行拦截。
Executor接口方法主要有update、query、commit、rollback等等。
主要思路为:
- 进入拦截器方法中
- 获取拦截器方法参数
- 获取解析参数及MappedStatement
- 从MappedStatement声明类中获取resultMap
- 获取resultMappings并且进行自定义
- 重新组装新的ResultMap
- 利用反射将新的ResultMap设置进入MappedStatement中
拦截器代码
import org.apache.ibatis.cache.CacheKey;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.ResultMap;
import org.apache.ibatis.mapping.ResultMapping;
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.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.springframework.stereotype.Component;
import org.springframework.util.ReflectionUtils;
import java.lang.reflect.Field;
import java.util.*;
@Component
@Intercepts({@org.apache.ibatis.plugin.Signature(type = Executor.class, method = "query",
args = {
MappedStatement.class,
Object.class,
RowBounds.class,
ResultHandler.class,
CacheKey.class,
BoundSql.class})})
public class MybatisInterceptorConfig implements Interceptor {
/*重置ResultMapping*/
private List<ResultMapping> resetResultMap(List<ResultMapping> resultMaps){
//ResultMaps.add
return resultMaps;
}
@Override
public Object intercept(Invocation invocation) throws Throwable {
resetResultMap(invocation);
return invocation.proceed();
}
@Override
public Object plugin(Object o) {
return Plugin.wrap(o, this);
}
@Override
public void setProperties(Properties properties) {
}
private void resetResultMap(Invocation invocation) {
final Object[] args = invocation.getArgs();
MappedStatement mappedStatement = (MappedStatement) args[5];
ResultMap resultMap = mappedStatement.getResultMaps().iterator().next();
if (resultMap != null) {
List<ResultMapping> resultMappings = resultMap.getResultMappings();
if (resultMappings != null && !(resultMappings instanceof AdjustedList)) {
List<ResultMapping> newResultMappings = this.resetResultMap(new AdjustedList(resultMappings));
ResultMap newResultMap = new ResultMap.Builder(mappedStatement.getConfiguration(), resultMap.getId(), resultMap.getType(), newResultMappings).build();
Field field = ReflectionUtils.findField(MappedStatement.class, "resultMaps");
ReflectionUtils.makeAccessible(field);
ReflectionUtils.setField(field, mappedStatement, Collections.singletonList(newResultMap));
}
}
}
private class AdjustedList<E> extends ArrayList<E> {
public AdjustedList(Collection<? extends E> c) {
super(c);
}
}
}