MyBatis一对多关联查询报TooManyResultsException问题求助
问题解决思路与方案
问题根源
- 方法与XML配置不匹配:你调用的
getPlayersByClubByName方法,在XML中找不到同名的select节点(XML里定义的是getClubByName),MyBatis无法正确识别执行逻辑,默认以selectOne执行查询,但你的SQL返回了2条结果(对应2个Player),直接触发TooManyResultsException。 - 结果映射错误:你定义了处理一对多关系的
resultMap,但select标签里用了resultType="Club",既没用到自定义映射,且返回类型和你要的Set<Player>完全不匹配。
两种修正方案(均为XML方式)
方案一:获取包含球员列表的俱乐部对象
如果你的需求是拿到俱乐部及其关联的所有球员,按以下步骤修改:
- 修正Mapper接口方法:
Club getClubByName(String name);
- 完善XML配置:
<mapper namespace="uk.co.redfruit.gdx.velvetbelly.core.data.mappers.ClubMapper" > <!-- 完整的Club结果映射,补充Player的所有字段映射 --> <resultMap id="ClubResultMap" type="Club" > <result property="id" column="id" /> <result property="name" column="name" /> <collection property="players" ofType="Player" > <result property="id" column="player_id" /> <result property="firstName" column="player_firstName" /> <result property="lastName" column="player_lastName" /> </collection> </resultMap> <select id="getClubByName" resultMap="ClubResultMap" > select c.id as id, c.name as name, p.id as player_id, p.firstName as player_firstName, p.lastName as player_lastName from clubs c inner join players p on c.id = p.club where c.name = #{name} </select> </mapper>
调用时通过Club club = mapper.getClubByName("Testers United");获取俱乐部,再从club.getPlayers()拿到球员集合。
方案二:直接获取指定俱乐部的球员集合
如果只需要球员列表,无需俱乐部信息,直接单独写查询:
- 修正Mapper接口方法:
Set<Player> getPlayersByClubByName(String name);
- 添加对应XML配置:
<mapper namespace="uk.co.redfruit.gdx.velvetbelly.core.data.mappers.ClubMapper" > <select id="getPlayersByClubByName" resultType="Player" > select id, firstName, lastName from players where club = (select id from clubs where name = #{name}) </select> </mapper>
这样调用Set<Player> players = mapper.getPlayersByClubByName("Testers United");即可正常返回结果,不会触发异常。
关键注意事项
- 接口方法名必须和XML中
select节点的id完全一致,MyBatis依赖名称绑定方法与SQL。 - 处理一对多关联时,必须使用
resultMap配置<collection>,不能用resultType直接映射。 - 当SQL返回多条结果时,接口方法的返回类型必须是集合(List/Set等),否则MyBatis会用
selectOne执行,导致结果数量不匹配的异常。
内容的提问来源于stack exchange,提问作者Paul Hunnisett
相关产品推荐
相关产品推荐

