@Mapkey的使用
在多值查询的时候,通常要把方法返回类型设置为List<Dto>类型,Mybatis为我们提供了另一种解决方式,通过K-V的形式将查询结果保存在Map中,这种实现方式只需要在方法上标注为@Mapkey即可。
如下代码:查询一个学生表,包含id,name,age三个字段,使用@mapkey将id号作为K,查询结果作为V.使用@Mapkey时最好将K设置为唯一的,否则后续的结果将会覆盖已查询到的结果,如果设置的@Mapkey设置的value为空或者一个跟查询结果不匹配的字段,那么查到的记录K成了null,查询结果始终都是最后一条。这个可以通过源码中的DefaultMapResultHandler<K, V>类得出结果,代码见最后, final K key = (K) mo.getValue(mapKey);这句代码就是将@Mapkey中指定的类型字段查询出对应的value值,再将value值作为最终结果的key。
1 package com.zzz.mybatis.mapper; 2 3 import java.util.List; 4 import java.util.Map; 5 6 import org.apache.ibatis.annotations.Flush; 7 import org.apache.ibatis.annotations.MapKey; 8 import org.apache.ibatis.annotations.Select; 9 10 public interface SqlMapper { 11 12 public List<Map<String, Object>> list(); 13 14 @Flush 15 public void flush(); 16 17 @MapKey(value="id") 18 @Select("select id,name,age from student") 19 public Map<String,Map<String,String>> listByMapkey(); 20 }
相关测试类
1 package com.zzz.mybatis.service; 2 3 import java.util.List; 4 import java.util.Map; 5 6 import org.apache.ibatis.session.SqlSession; 7 import org.apache.ibatis.session.SqlSessionFactory; 8 import org.apache.ibatis.session.SqlSessionFactoryBuilder; 9 import org.junit.Before; 10 import org.junit.Test; 11 12 import com.zzz.mybatis.mapper.SqlMapper; 13 import com.zzz.mybatis.mapper.StudentMapper; 14 15 public class StudentMapperTest { 16 private SqlSession session; 17 18 private StudentMapper mapper; 19 20 @Before 21 public void before() { 22 SqlSessionFactoryBuilder builder =new SqlSessionFactoryBuilder(); 23 SqlSessionFactory sessionFactory=builder.build(Class.class.getResourceAsStream("/mybatis-config.xml")); 24 this.session=sessionFactory.openSession(false); 25 } 26 @Test 27 public void getStuByMapkey() { 28 mapper=session.getMapper(StudentMapper.class); 29 mapper.flush(); 30 Map<String, Map<String, String>> rs=mapper.listByMapkey(); 31 System.out.println(rs.toString()); 32 } 33 }
测试结果
{1={name=zhangsan, id=1, age=20}, 2={name=lisi, id=2, age=30}, 3={name=wangwu, id=3, age=40}}
DefaultMapResultHandler<K, V>
1 @Override 2 public void handleResult(ResultContext<? extends V> context) { 3 final V value = context.getResultObject(); 4 final MetaObject mo = MetaObject.forObject(value, objectFactory, objectWrapperFactory, reflectorFactory); 5 // TODO is that assignment always true? 6 final K key = (K) mo.getValue(mapKey); 7 mappedResults.put(key, value); 8 }