MyBatis Mapper查询返回结果重复问题排查:数据库仅两条数据却返回四条结果
为什么MyBatis查询返回重复的结果?
这个问题很典型,我来帮你拆解一下原因和解决方案:
问题根源:SQL逻辑错误导致重复输出
先看你写的Mapper SQL代码:
<select id="selectList" resultType="map" > <foreach collection="list" item="items" separator=" union all "> SELECT #{items.id,jdbcType=INTEGER} id, #{items.name,jdbcType=VARCHAR} name FROM category </foreach> </select>
这段代码的实际执行逻辑是:
- 对于你传入的List里的每一个元素(也就是map1和map2),都会执行一次查询
- 每次查询都会取出category表中的所有行,然后把每行的
id替换成你传入的items.id,name替换成你传入的items.name - 最后用
union all把两次查询的结果合并
因为你的category表本身有2条数据,所以第一次循环(对应map1的id=1、name=haha)会返回2条完全一样的{id=1, name=haha};第二次循环(对应map2的id=2、name=update)又返回2条完全一样的{id=2, name=update}。加起来就是2+2=4条结果,这就是你看到重复的原因。
针对不同需求的解决方案
需求1:查询category表中与传入id匹配的真实数据
如果你是想根据传入的id列表,获取category表中对应的真实记录,应该修改SQL为带条件的查询:
<!-- 用union all的写法 --> <select id="selectList" resultType="map" > <foreach collection="list" item="items" separator=" union all "> SELECT id, name FROM category WHERE id = #{items.id,jdbcType=INTEGER} </foreach> </select>
或者更高效的IN子句写法(推荐,减少SQL拼接次数):
<select id="selectList" resultType="map" > SELECT id, name FROM category WHERE id IN <foreach collection="list" item="items" open="(" separator="," close=")"> #{items.id,jdbcType=INTEGER} </foreach> </select>
需求2:直接返回传入的id和name数据(不需要查询表)
如果你本来就只是想输出你传入的那两组数据,根本不需要关联category表,那去掉FROM category即可(MySQL可以直接省略FROM,Oracle需要用FROM dual):
<select id="selectList" resultType="map" > <foreach collection="list" item="items" separator=" union all "> SELECT #{items.id,jdbcType=INTEGER} id, #{items.name,jdbcType=VARCHAR} name </foreach> </select>
总结
核心问题是你原SQL中每个foreach循环都全表扫描了category,把表中每一行都用传入参数替换字段值后再合并,自然产生了重复结果。根据你的实际业务需求调整SQL逻辑就能解决问题啦。
内容的提问来源于stack exchange,提问作者鹰 9am
相关产品推荐
相关产品推荐

