MyBatis使用collection标签查询时如何保留重复数据
MyBatis结果映射重复数据保留方案
问题根因
MyBatis结果映射默认通过唯一标识区分不同记录:如果显式配置了<id>标签就用该标签值作为唯一标识,未配置时会把所有<result>字段的组合值作为唯一标识,相同标识的记录会自动合并去重。你当前的配置没有指定唯一标识,且使用<collection>映射字段时,相同值的元素会被自动合并。
解决方案
方案1:给ResultMap添加唯一ID标识(最推荐)
在结果映射顶层添加对应查询结果唯一列的<id>标签,比如数据库主键、临时行号等,示例配置如下:
<resultMap id="自定义resultMapId" type="你的实体类全限定名"> <!-- 新增id标签,column对应查询结果唯一列名,property对应实体类字段名 --> <id column="id" property="id" jdbcType="BIGINT"/> <!-- 原有collection配置保持不变 --> <collection property="studentName" ofType="java.lang.String"> <result column="student_name"/> </collection> <collection property="studentClass" ofType="java.lang.String"> <result column="student_class"/> </collection> <collection property="studentGrade" ofType="java.lang.String"> <result column="student_grade"/> </collection> </resultMap>
如果查询结果没有原生唯一列,可以在SQL语句中用ROW_NUMBER() OVER() AS row_id生成临时唯一行号,将row_id映射为<id>即可。
方案2:调整映射标签(适用单值字段场景)
如果你要映射的是每行对应单个学生姓名、班级、年级的单值场景,属于标签使用错误,<collection>是用来映射一对多的集合属性的,直接替换为普通<result>标签即可完全避免去重问题:
<resultMap id="自定义resultMapId" type="你的实体类全限定名"> <result property="studentName" column="student_name" jdbcType="VARCHAR"/> <result property="studentClass" column="student_class" jdbcType="VARCHAR"/> <result property="studentGrade" column="student_grade" jdbcType="VARCHAR"/> </resultMap>
方案3:绕过结果缓存去重逻辑
如果确实需要保留集合内的所有重复元素,可直接在对应<select>查询标签上添加resultSetType="FORWARD_ONLY"属性,绕过MyBatis的结果缓存去重逻辑:
<select id="你的Mapper接口方法名" resultMap="自定义resultMapId" resultSetType="FORWARD_ONLY"> 你的查询SQL语句 </select>
内容的提问来源于stack exchange,提问作者Duelist Grand
相关产品推荐
相关产品推荐

