业务场景
有时候我们需要分组统计某个字段的数量,一般在返回结果中我们需要用resultMap做映射或者直接将字段通过resultType映射到返回的对象上,只要保证字段别名和返回对象中的属性是一致的即可。但是如果我们不想在返回的对象中新增字段呢?例如:通过某个字段分组计算的条数可能往往我们并不想新增一个属性在返回的对象里。
痛点
如果resultType是具体的返回对象,需要在返回的对象中专门新增一个字段(如xxCount)来表示这个查询结果的数量。如果返回的是resultMap,同样也需要在返回的对象中做映射。
解决方式
这个时候可以通过resultType="java.util.Map"返回。
<select id="countGroupByGroupCode" parameterType="xx.xx.xx.xx.query_object.DictQuery" resultType="java.util.Map">
SELECT
group_code AS groupCode,
count(*) AS count
FROM t_dict
<include refid="BaseWhereCondition"/>
GROUP BY group_code;
</select>
resultType="java.util.Map"的解释
MyBatis会将字段名称作为key,字段的值作为value。比如在返回的一个map中,把groupCode作为key把它具体的值作为value,把count作为key把它具体的值作为value。
List<Map<String, Object>>
如果满足条件的数据有多条,在Mapper.java接口中返回类型为Map<String, Object>的话,是会报错的,因为这样的返回类型只支持返回一条数据,这个时候就需要定义成List<Map<String, Object>>,map的value定义成Object是因为返回的既有数字也有字符串,方便做兼容。
List<Map<String, Object>> countGroupByGroupCode(DictQuery dictQuery);
如果方法名下面报红线提示“@MapKey is required ”,不要在意,在下面会解释。
测试结果如下返回的数据如下:
[
{
"count": 2,
"groupCode": "groupCode01"
},
{
"count": 1,
"groupCode": "groupCode02"
}
]
list里面每一个元素都是一个map,key是count和groupCode。
@Mapkey
如果我们想只返回一个map,这个map的key是我sql查询结果中可以区分唯一的一个字段,我们想通过map.get(“key”)直接拿到具体的值,就可以在Mapper.java中添加这个注解,比如map.get(“groupCode01”)得到"{“count”: 2,“groupCode”: “groupCode01”}"。
@MapKey("groupCode")
Map<String, Object> countGroupByGroupCode(DictQuery dictQuery);
注意:
- 加了注解【@MapKey】,groupCode是可以区分唯一的;
- 这个时候的返回类型不应该用List<>了。
{
"groupCode02": {
"count": 1,
"groupCode": "groupCode02"
},
"groupCode01": {
"count": 2,
"groupCode": "groupCode01"
}
}
重点:从返回的结果中我们能看出来,map的key已经是具体的值了,如groupCode01和groupCode02。