You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Mybatis中resultMap的association与collection能否混用?结果映射异常求助

问题:MyBatis 1:n关联查询结果重复,集合未正确聚合

team表与schedule表为1:n关联关系,编写查询球队预约详情的SQL及ResultMap后,返回结果出现多条重复Team对象、dates仅含单个日期的记录,期望单个Team对象对应所有预约日期列表。

现有SQL语句

<select id="getTeamSchdules" resultMap="teamResultMap">
    select a.team_id, a.team_name, b.sche_date
    from team a, schedule b
    where 1 = 1
      and a.STADIUM_ID = b.stadium_id
      and a.team_id = #{teamId}
</select>

现有ResultMap配置

<resultMap id="teamResultMap" type="com.example.api.domain.team.domain.TeamSchedulerInfo">
    <association property="team" javaType="com.example.api.domain.team.domain.Team">
        <result property="teamId" column="team_id"/>
        <result property="teamName" column="team_name" />
    </association>
    <collection property="dates" column="stadium_id" javaType="list" ofType="string">
        <result column="sche_date" />
    </collection>
</resultMap>

对应的Java POJO

@Data
public class Team {
    private String teamId;
    private String teamName;
}

@Data
public class TeamSchedulerInfo {
    private Team team;
    private List<String> dates;
}

当前错误返回结果

[
    {
        "team": {
            "teamId": "K04",
            "teamName": "UNITED"
        },
        "dates": [
            "20120324"
        ]
    },
    {
        "team": {
            "teamId": "K04",
            "teamName": "UNITED"
        },
        "dates": [
            "20120414"
        ]
    },
    {
        "team": {
            "teamId": "K04",
            "teamName": "UNITED"
        },
        "dates": [
            "20121117"
        ]
    }
]

期望返回结果

[
    {
        "team": {
            "teamId": "K04",
            "teamName": "UNITED"
        },
        "dates": [
            "20120324",
            "20120414",
            "20121117"
        ]
    }
]

解决方案

问题核心是MyBatis无法自动识别主表的唯一标识来聚合关联数据,并非association与collection不能同时使用,你的使用方式存在两处关键错误:

1. 给ResultMap配置主对象的唯一标识(id标签)

MyBatis需要通过唯一标识判断哪些行属于同一个主对象,从而聚合集合数据。修改ResultMap,给关联的team对象以及外层TeamSchedulerInfo添加id标签(对应team的主键team_id),同时移除collection的冗余column属性:

<resultMap id="teamResultMap" type="com.example.api.domain.team.domain.TeamSchedulerInfo">
    <!-- 配置外层对象的唯一标识,对应team_id -->
    <id property="team.teamId" column="team_id"/>
    <association property="team" javaType="com.example.api.domain.team.domain.Team">
        <!-- 配置association的唯一标识 -->
        <id property="teamId" column="team_id"/>
        <result property="teamName" column="team_name" />
    </association>
    <!-- 无需指定column,MyBatis会根据主标识自动聚合集合数据 -->
    <collection property="dates" javaType="list" ofType="string">
        <result column="sche_date" />
    </collection>
</resultMap>

2. 优化SQL语句(可选,提升可读性)

原SQL使用隐式内连接,建议改用显式JOIN语法,逻辑更清晰:

<select id="getTeamSchdules" resultMap="teamResultMap">
    select a.team_id, a.team_name, b.sche_date
    from team a
    join schedule b on a.STADIUM_ID = b.stadium_id
    where a.team_id = #{teamId}
</select>

原理说明

当MyBatis查询到多行结果时,会通过id标签指定的字段判断是否为同一个主对象:

  • 若team_id相同,则将当前行的sche_date追加到已存在的dates集合中
  • 若team_id不同,则创建新的TeamSchedulerInfo对象

这样就能实现单个Team对象对应所有预约日期的聚合效果。


内容的提问来源于stack exchange,提问作者koreanDev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 17:01:13