拦截器(二)

  使用Mybatis进行系统开发的时候,会有这么一种需求:希望通过Mybatis查询某一个表返回的结果是一个Map,而这个Map的Key是表的一个字段,Value是另一个字段。按照Mybatis的做法,指定查询Mapper语句的resultType为map时返回的结果是一个Map列表(表中有多条记录时),而且每个元素Map对应的是表的一行记录(Key为每个字段的名称,Value为对应的值),这跟需求是不相符合的。那有什么方法可以让Mybatis查询出来的结果是一个Key为表中某一列的值,Value为表中另一列的值的Map呢?

实现

       返回结果是由ResultSetHandler的handleResultSets方法对当前的Statement处理后的返回结果,所以如果要改变返回结果的话,就需要使用Mybatis的拦截器对ResultSetHandler接口的handleResultSets方法进行拦截。

  我们不可能把所有的ResultSet都拦截,然后返回对应的Map,所以需要在拦截到handleResultSets方法之后进行筛选,对于不需要拦截的调用Invocation的proceed()方法,需要拦截的则实现自己的逻辑,返回对应的结果。对于这种筛选条件一般是通过ParameterObject来进行的。这里定义一个类,叫MapParam,当某一个语句需要返回一个Map时,就指定其参数类型为MapParam

  这个参数类型ParamMap一定需要有三个作用:

  • (1)    可以指定哪个字段为返回Map的Key;
  • (2)    可以指定哪个字段为返回Map的Value;
  • (3)    可以附带其他参数;
package mybatis.parameter;
import java.util.HashMap;

public class ParamMap extends HashMap<String,Object> {

    private final static String keyField="keyField";
    private final static String valueField="valueField";

    public ParamMap(){}

    public ParamMap(Object key,Object value){
        put(keyField,key);
        put(valueField,value);
    }

}

  定义一个MapInterceptor用于拦截对应的结果集返回一个Map

package mybatis.interceptor;

import mybatis.parameter.ParamMap;
import mybatis.util.ReflectUtil;
import org.apache.ibatis.executor.parameter.ParameterHandler;
import org.apache.ibatis.executor.resultset.DefaultResultSetHandler;
import org.apache.ibatis.executor.resultset.ResultSetHandler;
import org.apache.ibatis.plugin.*;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Properties;

@Intercepts(@Signature(method="handleResultSets",type= ResultSetHandler.class,args={Statement.class}))
public class MapInterceptor implements Interceptor {
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        Object target = invocation.getTarget();
        if(target instanceof DefaultResultSetHandler){
            DefaultResultSetHandler handler=(DefaultResultSetHandler)target;
            ParameterHandler parameterHandler = (ParameterHandler) ReflectUtil.getFieldValue(handler, "parameterHandler");
            Object parameterObject = parameterHandler.getParameterObject();
            if(parameterObject instanceof ParamMap){
                ParamMap paramMap=(ParamMap)parameterObject;
                Statement statement = (Statement) invocation.getArgs()[0];
                return handleResultSet(statement.getResultSet(),paramMap);
            }
        }
        return invocation.proceed();
    }

    private Object handleResultSet(ResultSet resultSet, ParamMap paramMap) {
        if(resultSet!=null){

            HashMap<Object, Object> map = new HashMap<>();

            List<Object> resultList=new ArrayList<Object>();
            try {
                while (resultSet.next()) {
                    Object keyFiledValue=resultSet.getObject(ParamMap.keyField);
                    Object valueFieldValue=resultSet.getObject(ParamMap.valueField);
                    map.put(keyFiledValue,valueFieldValue);
                }
                //handleResultSet的返回值为List
                resultList.add(map);
            }catch (SQLException e){

            }finally {
                try {
                    resultSet.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            return resultList;
        }
        return null;
    }

    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target,this);
    }

    @Override
    public void setProperties(Properties properties) {

    }
}

  Map文件中的配置

  <select id="findByParamMap" resultType="map" parameterType="paramMap">
        select username,regTime from user
    </select>

  测试:

  @Test
    public void testParamMap(){
        SqlSession sqlSession=null;
        try {
            sqlSession=SqlSessionFactoryUtil.openSession();
            UserMapper sqlSessionMapper = sqlSession.getMapper(UserMapper.class);
            ParamMap paramMap = new ParamMap();
            paramMap.put("name","regTime");
            Map map = sqlSessionMapper.findByParamMap(paramMap);
            System.out.println(map);
        }finally {
            sqlSession.close();
        }
    }

 

参考:

http://elim.iteye.com/blog/1942464

posted on 2018-11-05 19:44  溪水静幽  阅读(207)  评论(0)    收藏  举报