今天在进行mybatis学习时 出现了上述错误 在网上看了n篇文章都没有解决
下图是我查询用到的两个表 其中student表中的tid和teacher表中的id通过外键链接
在我的xml文件中 我刚开始是这么进行查询的
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--namespace会绑定一个对应的Mapper接口-->
<mapper namespace="com.dao.teacherMapper">
<select id="getTeacher" resultMap="tns">
select s.id,t.id ,s.name ,t.name
from smbms.student s,smbms.teacher t
where s.tid = t.id and t.id=#{tidd} tidd来源于下文mapper文件
</select>
<resultMap id="tns" type="com.pojo.Teacher">
<result property="id" column="t.id"/>
<result property="name" column="t.name"/>
<collection property="students" ofType="com.pojo.Student">
<result property="id" column="s.id"/>
<result property="name" column="s.name"/>
<result property="tid" column="t.id"/>
</collection>
</resultMap>
</mapper>
public interface teacherMapper {
Teacher getTeacher(@Param("tidd") int id);
}
可以看到 从语法上来说 没有任何问题 如果直接使用以下sql语句 执行查询 是可以得到结果的
select s.id,t.id ,s.name ,t.name
from smbms.student s,smbms.teacher t
where s.tid = t.id and t.id= 1
但是为什么在mybatis中总是提示Expected one result (or null) to be returned by selectOne(), but found: 3 意思是 预期返回一个结果 但是 返回了三个
检查了无数次语法以及mybatis配置均没发现问题 后来看了这篇博客mybatis一对多映射时始终不能正确映射到实体类,报错:Expected one result (or null) to be returned by selectOne(),but found:_qq_41536791的博客-CSDN博客_mybatis一对多映射失败https://blog.csdn.net/qq_41536791/article/details/104246507 博主表示自己是因为没有对主键进行查询 但是我这里s.id和t.id我都查了 还是不行 最后决定看一下Mybatis官方手册 (mybatis) 在官方手册里针对resultmap 有这么一段示例
注意这个联合查询, 以及采取保护来确保所有结果被唯一而且清晰的名字来重命名。
虽然这个示例是用来演示使用resultMap的便捷 但这个侧面就是在说 如果同时对两张表进行查询 且两张表有相同的字段名 那么一定要起别名来进行区分 这样resultMap才能完成正确的映射!
有了思路之后 对上面的代码进行了修改 给所有的属性起了别名 果然!查询成功!
<mapper namespace="com.dao.teacherMapper">
<select id="getTeacher" resultMap="tns">
select s.id sid,t.id tid,s.name sname,t.name tname
from smbms.student s,smbms.teacher t
where s.tid = t.id and t.id=#{tidd}
</select>
<resultMap id="tns" type="com.pojo.Teacher">
<result property="id" column="tid"/>
<result property="name" column="tname"/>
<collection property="students" ofType="com.pojo.Student">
<result property="id" column="sid"/>
<result property="name" column="sname"/>
<result property="tid" column="tid"/>
</collection>
</resultMap>
</mapper>
为了进一步验证 我针对两张表独有的字段 (student表中的tid)字段进行了查询 且没有起别名
发现同样可以查询到结果
<mapper namespace="com.dao.teacherMapper">
<select id="getTeacher" resultMap="tns">
select s.id sid,t.id tid1,s.name sname,t.name tname,s.tid
from smbms.student s,smbms.teacher t
where s.tid = t.id and t.id=#{tidd}
</select>
<resultMap id="tns" type="com.pojo.Teacher">
<result property="id" column="tid1"/>//这里的id让它等于select中查询的tid1
<result property="name" column="tname"/>
<collection property="students" ofType="com.pojo.Student">
<result property="id" column="sid"/>
<result property="name" column="sname"/>
<result property="tid" column="tid"/>//这里的tid 可以等于Student表里的tid
//也可以等于teacher表里的id 两者都代表教师id
//这里让它直接等于select中查询的s.tid(等于Student表里的tid)
</collection>
</resultMap>
但是如果我们取消相同字段名的别名 比如name 那么会发现查询结果中的name变成了null
如果取消两张表主键的别名 就会报之前的错误 Expected one result (or null) to be returned by selectOne(), but found: 3
综上 结果说明resultmap在映射的时候 是会把多张表中相同的字段名 当成同一个对象来看待 比如上文中的s.id和t.id resultmap在映射的时候会把两者都当成id 而不是一个当成s.id另一个当成t.id 来区分