概述

MyBatis 会将查询结果保存在 HashMap 中,所以,如果查询出来的结果集中包含相同的记录,最后一个记录将会覆盖前面所以的记录,到最后只剩下一条记录。

背景

最近做到一个项目,其中需要统计程序评判的所有结果。其中测试数据有多个,如果所有的测试数据都失败了,那么结果将会一样。

查询数据库

未使用 id 之前的 mapper.xml 代码,

1
2
3
4
5
<resultMap type="**.pojo.JudgeResult2" id="JudgeResultMap">
<result column="runtime" property="runtime" jdbcType="INTEGER" />
<result column="memory" property="memory" jdbcType="INTEGER" />
<result column="message" property="message" jdbcType="VARCHAR" />
</resultMap>

首先贴出数据库中的记录

1
2
3
4
5
6
7
8
9
10
11
psid rtid runtime memory
140 7 0 0
140 7 0 0
140 7 0 0
140 7 0 0
140 7 0 0
140 7 0 0
140 7 0 0
140 7 0 0
140 7 0 0
140 7 0 0

上述十条记录完全重复若使用上述的 resultMap,查询到的结果将是

1
2
3
4
5
6
7
8
9
{
"type": {
"id": 7,
"name": "结果错误"
},
"runtime": 0,
"memory": 0,
"message": null
}

查看查询日志信息发现,确实查询到了 10 条记录,但是最后的记过仍旧只有一条记录。百思不得其解。

最后发现一个规律,就是重复的记录都会变成一条记录,于是就想到了跟踪 MyBatis 的源码,发现其采用 HashMap 保存结果集,导致记录被覆盖。

解决方案

resultMap 中必须保证有一个 id,只要能表示记录的唯一性即可。即使冗余也是值得的

1
2
3
4
5
6
<resultMap type="**.pojo.JudgeResult2" id="JudgeResultMap">
<id column="sdid" property="sdid" jdbcType="INTEGER" />
<result column="runtime" property="runtime" jdbcType="INTEGER" />
<result column="memory" property="memory" jdbcType="INTEGER" />
<result column="message" property="message" jdbcType="VARCHAR" />
</resultMap>