Bootstrap

MyBatis查询两个字段,返回Map,一个字段作为key,一个字段作为value的实现

1. 问题描述

  在使用MyBatis,我们经常会遇到这种情况:SELECT两个字段,需要返回一个Map,其中第一个字段作为key,第二个字段作为value。MyBatis的MapKey虽然很实用,但并不能解决这种场景。这里,就介绍一种使用拦截器来解决这个问题的方案。

2. 解决方案

源码详见:spring-mybatis-test

2.1 注解

package com.adu.spring_test.mybatis.annotations;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 将查询结果映射成map的注解,其中第一个字段为key,第二个字段为value.
 * <p>
 * 注:返回类型必须为{
    @link java.util.Map Map<K, V>}。K/V的类型通过MyBatis的TypeHander进行类型转换,如有必要可自定义TypeHander。
 *
 * @author yunjie.du
 * @date 2016/12/22 18:44
 */
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD })
public @interface MapF2F {
    /**
     * 是否允许key重复。如果不允许,而实际结果出现了重复,会抛出org.springframework.dao.DuplicateKeyException。
     * 
     * @return
     */
    boolean isAllowKeyRepeat() default true;

    /**
     * 对于相同的key,是否允许value不同(在允许key重复的前提下)。如果允许,则按查询结果,后面的覆盖前面的;如果不允许,则会抛出org.springframework.dao.DuplicateKeyException。
     * 
     * @return
     */
    boolean isAllowValueDifferentWithSameKey() default false;
}

 

 

 

2.2 拦截器

package com.adu.spring_test.mybatis.interceptor;

import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
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.Map;
import java.util.Objects;
import java.util.Properties;

import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.executor.resultset.ResultSetHandler;
import org.apache.ibatis.mapping.MappedStatement;
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.plugin.Signature;
import org.apache.ibatis.reflection.MetaObject;
;