mybatis - 基于拦截器修改执行语句中的ResultMap映射关系

拦截器介绍

mybatis提供了@Intercepts注解允许开发者对mybatis的执行器Executor进行拦截。
Executor接口方法主要有update、query、commit、rollback等等。
主要思路为:

  1. 进入拦截器方法中
  2. 获取拦截器方法参数
  3. 获取解析参数及MappedStatement
  4. 从MappedStatement声明类中获取resultMap
  5. 获取resultMappings并且进行自定义
  6. 重新组装新的ResultMap
  7. 利用反射将新的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 resetResultMap(List 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 resultMappings = resultMap.getResultMappings();
            if (resultMappings != null && !(resultMappings instanceof AdjustedList)) {
                List 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 extends ArrayList {
        public AdjustedList(Collection c) {
            super(c);
        }
    }
}

你可能感兴趣的:(mybatis - 基于拦截器修改执行语句中的ResultMap映射关系)