mybatis resultMap collection聚合String

发布时间:2025-12-09 11:45:08 浏览次数:1

背景

  • 主表index_dict_data

  • 内容表index_dict_cn_name

  • 期望输出数据结构:即联表之后根据indexId聚合,然后将cnName字段聚合到一个List<String>

    [    {        "indexId": "pageCrashNum",        "cnNames": ["崩溃数","崩溃数"]    },    {        "indexId": "pageCrashRate",        "cnNames": ["崩溃率","崩溃率"]    },    {        "indexId": "pageCrashUserNum",        "cnNames": ["崩溃用户数","崩溃用户数"]    }]

配置

mapper.xml

<resultMap  type="com.wf.indexmetrics.IndexMetricsDictionary">    <result column="indexId" property="indexId"/>    <collection property="cnNames" javaType="list" ofType="java.lang.String">        <!--虽然配置多个字段, 但是只会返回第一个, 但是聚合的时候会加入其他字段作为key-->        <result column="cnName"/>        <!--必须有唯一id, 否则对于相同的cnName为只保留一个-->        <result column="cnNameId"/>    </collection></resultMap><select  resultMap="dictMap">    select    tidd.index_id as indexId,    tidd.dimension as dimension,    cn.cn_name as cnName,    cn.id as cnNameId    FROM    index_dict_data tidd    LEFT JOIN index_dict_cn_name cn ON cn.index_id = tidd.index_id    <where>        and tidd.index_id in        <foreach collection="indexKeys" open="(" separator="," close=")" item="item">            #{item}        </foreach>    </where></select>

源码解析

  • org.apache.ibatis.executor.resultset.DefaultResultSetHandler#applyNestedResultMappings
private boolean applyNestedResultMappings(ResultSetWrapper rsw, ResultMap resultMap, MetaObject metaObject, String parentPrefix, CacheKey parentRowKey, boolean newObject) {    boolean foundValues = false;    for (ResultMapping resultMapping : resultMap.getPropertyResultMappings()) {        final String nestedResultMapId = resultMapping.getNestedResultMapId();        if (nestedResultMapId != null && resultMapping.getResultSet() == null) {            try {                final String columnPrefix = getColumnPrefix(parentPrefix, resultMapping);                final ResultMap nestedResultMap = getNestedResultMap(rsw.getResultSet(), nestedResultMapId, columnPrefix);                if (resultMapping.getColumnPrefix() == null) {                    // try to fill circular reference only when columnPrefix                    // is not specified for the nested result map (issue #215)                    Object ancestorObject = ancestorObjects.get(nestedResultMapId);                    if (ancestorObject != null) {                        if (newObject) {                            linkObjects(metaObject, resultMapping, ancestorObject); // issue #385                        }                        continue;                    }                }                // rowKey实际为-2048015495:-685734919:com.sf.dev.mapper.IndexMetricsDictNewMapper.mapper_resultMap[dictMap]_collection[cnNames]:cnName:崩溃率:cnNameId:1008                final CacheKey rowKey = createRowKey(nestedResultMap, rsw, columnPrefix);                // combinedKey实际为-381970743:-2436525477:com.sf.dev.mapper.IndexMetricsDictNewMapper.mapper_resultMap[dictMap]_collection[cnNames]:cnName:崩溃率:cnNameId:1008:-1750790558:-229051733:com.sf.dev.mapper.IndexMetricsDictNewMapper.dictMap:metricsKey:pageCrashRate:dimension:%                final CacheKey combinedKey = combineKeys(rowKey, parentRowKey);                // 此处通过combinedKey判断是否已存在值, 如果只有cnName而没有cnNameId就会判断已存在, 在后面的逻辑就不会再加入到List                Object rowValue = nestedResultObjects.get(combinedKey);                boolean knownValue = rowValue != null;                instantiateCollectionPropertyIfAppropriate(resultMapping, metaObject); // mandatory                if (anyNotNullColumnHasValue(resultMapping, columnPrefix, rsw)) {                    rowValue = getRowValue(rsw, nestedResultMap, combinedKey, columnPrefix, rowValue);                    if (rowValue != null && !knownValue) {                        // 把cnName add到List                        linkObjects(metaObject, resultMapping, rowValue);                        foundValues = true;                    }                }            } catch (SQLException e) {                throw new ExecutorException("Error getting nested result map values for '" + resultMapping.getProperty() + "'.  Cause: " + e, e);            }        }    }    return foundValues;}

问题

  • 起初没有配置cnNameId,保持唯一性,导致相同的cnName只保留了1个,实际应该保留2个

参考

  • Mybatis resultMap 嵌套集合

  • mybatis 结果映射 collection oftype为string,integer等类型

dict.cn
需要做网站?需要网络推广?欢迎咨询客户经理 13272073477