背景
-
主表index_dict_data
-
内容表index_dict_cn_name
-
期望输出数据结构:即联表之后根据indexId聚合,然后将cnName字段聚合到一个List<String>中
[ { "indexId": "pageCrashNum", "cnNames": ["崩溃数","崩溃数"] }, { "indexId": "pageCrashRate", "cnNames": ["崩溃率","崩溃率"] }, { "indexId": "pageCrashUserNum", "cnNames": ["崩溃用户数","崩溃用户数"] } ]
配置
mapper.xml
<resultMap id="dictMap" 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 id="getIndexMetricsList" 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个