1. 问题由来
当resultType若为Map时,若定义了Map的泛型为String,但是数据库返回字段在库中为Number,那么就会发现虽然Map中有值,但是其类型为Integer,泛型并没有起作用。因为Java语言的泛型采用的是擦除法实现的伪泛型,泛型信息(类型变量、参数化类型)编译之后通通被除掉了。
当resultMap中指定的JavaType是java.util.map,此处只指定类类型,而没指定泛型。而Map<String,String>和Map<String,Object>的类型是一样的,擦除去了泛型信息,因为Postgres数据库对于conf_map字段的定义为int4,故解析为Integer。mybatis将结果映射到map中的时候,使用的是反射,反射不检查泛型类型是否合法。所以在给conf_map字段赋值时是不会报错的。当需要操作Map的中的元素,在取出元素时,JVM就发现你要的类型是DictContent 而实际上是LinkedHashMap,就会抛出类型转换异常。
2. 设置
public class Test{
public static void main(String[] args) {
/*======================1========================*/
Map<String,String> map1 = new HashMap<>();
map1.put("key","1");
Map<String,Object> map2 = new HashMap<>();
map2.put("key", 1);
System.out.println(map1.getClass() == map2.getClass());//true
// 说明泛型类型String和Integer都被擦除掉了,只剩下原始类型。
/*======================2========================*/
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(1);
list.getClass().getMethod("add", Object.class).invoke(list, "asd");
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i)); // 会输出1和asd
}
}
}
3. 解决方案
1.自定义一个指定泛型的集合类替代List
2.自定义一个指定泛型的TypeHandler类