mybatis 笔记

发布时间 2023-06-16 13:44:29作者: Cinlap Soft

查询结果被合并

mapper 中定义的 sql 查询结果有3条,但执行 mapper 接口方法返回的实体列表只有1条,数据数量不符。这有可能是由于 xml 中的定义的 resultMap 有缺陷,如没有明确的定义一个用作主键的列,这分两种情况分别说明。

// reusltMap 定义
<resultMap id="vo" type="ProjectCentersStatisticsVo">
<association property="entityA" javaType ="domain.entityA">
<id property="id" column="id" />
</association>
</resultMap>

<select id="selectSql" resultMap="vo">
select id, name from t where xxx
</select>

第一种,resultMap 的定义中没有任何 result 或列,有的是 associationcollection association 中有id定义,此时,不会出现该问题,sql语句中出现的唯一的id被映射到entityA中的id
第二种,resultMap中定义了一个result,但它并不是id或者它在sql查询结果中并不是唯一的,但此时mybatis会将其看作主键来使用,值相同的结果被合并留下最后一条,会造成问题发生。

<resultMap id="vo" type="ProjectCentersStatisticsVo">
<result property="name" column="name" />
<association property="entityA" javaType ="domain.entityA">
<id property="id" column="id" />
</association>
</resultMap>

在上例中,resultMap中定义了一个name列,mybatis在处理查询结果时会将其作为主键,name相同的记录(行)将替代上一个,直至留下最后一个name不同的行。例如查询结果有3条,其中两条nametom,一条namejerry,mybatis处理后将返回2条记录,最后一条tom和唯一的一条jerry
第三种,为了避免发生上述问题,人为明确的定义一个主键在resultMap中,默认名字是id,如下

<resultMap id="vo" type="ProjectCentersStatisticsVo">
<result property="pk" column="pk" />
<result property="name" column="name" />
<association property="entityA" javaType ="domain.entityA">
<id property="id" column="id" />
</association>
</resultMap>

<select id="selectSql" resultMap="vo">
select id, id pk, name from t where xxx
</select>

在上例中,通过给resultMap增加一个pk字段来表示主键,在sql中增加一个pk列并为了保证其值的唯一用真的id填充,这样的好处是原本查询结果中的id字段还能正确映射到entityA中的id