最近正在学习MyBatis,发现这个MyBatis在处理对象间的关联关系的时候还是比较绕的,很难让人理解,所以,自己搜集了各种资料,并且亲身逐一进行测试,然后在这里写下这篇文章,就当是来理理自己的思路了。
其实不管是一对一映射还是一对多映射关系,在处理关联对象的时候都有两种方式,即使用嵌套的ResultMap和嵌套Select两种方式,本篇将以单、双向一对一为例来相信介绍关联映射的配置方式,一对多将在后续文章中介绍。
环境已准备好:
使用班级类Classes{id,name,teacherId}和老师类Teacher{id,name},一个老师对应着一个班级,Classes类中的teacherId引用Teacher类中的id,此外还有其对应的接口,其中各包含一个根据ID查询对象的方法。下面来完成根据Classes的Id来查询Classes并查询出 其关联的Teacher信息
一、单向的一对一
(1)使用嵌套Select的方式
所谓嵌套Select的方式,就是通过执行另外一个SQL映射语句来返回预期的复杂类型,其实说白了就是分别查询两张表的数据
1.实体类已创建,在Classes类中创建Teacher类的字段,表示单向一对一
2.创建ClassesMapper.xml文件,通过association元素来映射对象,编写如下配置:
<mapper namespace="com.wzj.dao.IClassesDao">
<resultMap type="com.wzj.entity.Classes" id="classesMap">
<id property="id" column="c_id" />
<result property="name" column="c_name" />
<!--省略普通属性 -->
<!--映射teacher对象,通过嵌套select语句方式,也就是再通过一条sql语句查询
property:java中字段名称,此处为teacher
select:使用另一个查询封装的结果
column:外键列,很重要,根据此列去查询对应的teacher -->
<association property="teacher" select="com.wzj.dao.ITeacherDao.selectTeacherById" column="teacher_id" />
</resultMap>
<!-- 根据接口中定义的方法来编写sql语句 -->
<select id="selectClassesById" resultMap="classesMap">
select * from classes where c_id=#{id}
</select>
</mapper>selectClassesById中的sql语句仅需要查询出Classes表的数据即可,然后映射的时候会再根据association中的select元素查询teacher表的数据,Teacher和CLasses是有关联的,查询Teacher必然要传递给其Id,那么这里的column就起到了作用了!
3.创建TeacherMapper.xml文件,这个就比较好配置了,不过也要注意sql语句:
<mapper namespace="com.wzj.dao.ITeacherDao">
<resultMap type="com.wzj.entity.Teacher" id="teacherMap">
<id property="id" column="t_id" />
<result property="name" column="t_name" />
</resultMap>
<!-- 根据参数来查询Teacher -->
<select id="selectTeacherById" resultMap="teacherMap">
select * from teacher where t_id=#{id}
</select>
</mapper> 4.创建测试类,运行正常输出了结果:
public static void main(String[] args) {
SqlSession session=MybatisUtil.currentSqlSession();
IClassesDao dao=session.getMapper(IClassesDao.class);
Classes c=dao.selectClassesById(1);
Teacher t=c.getTeacher();
System.out.println(c.getName()+"\t"+t.getName());
session.commit();
MybatisUtil.closeSqlSession();
} (2)使用嵌套的resultMap方式
在一条sql语句中使用连接查询出两张表的数据,然后在resultMap中再嵌套映射结果
1.对以上的ClassesMapper.xml进行修改:
<mapper namespace="com.wzj.dao.IClassesDao">
<resultMap type="com.wzj.entity.Classes" id="classesMap">
<id property="id" column="c_id" />
<result property="name" column="c_name" />
<!-- 同样使用association元素,标签不再是闭合,里面嵌套映射teacher对象的子标签
property:对象名称
javaType:声明要映射的类型完整名称或者别名
-->
<association property="teacher" javaType="com.wzj.entity.Teacher">
<id property="id" column="t_id" />
<result property="name" column="t_name" />
</association>
</resultMap>
<!-- 使用连接查询一并查出 -->
<select id="selectClassesById" resultMap="classesMap">
select * from classes c,teacher t where c.teacher_id=t.t_id and c.c_id=#{id}
</select>
</mapper>2.进行测试,正常输出结果:
IClassesDao dao=session.getMapper(IClassesDao.class);
Classes c=dao.selectClassesById(1);
Teacher t=c.getTeacher();
System.out.println(c.getName()+"\t"+t.getName());以上就是单向的一对一查询
二、双向一对一
其实明白了上面单向的一对一之后,双向的就简单了,一样的一个过程,本例以Classes中使用嵌套resultMap方式、Teacher中使用嵌套select来进行简单的阐述。
1.在Teacher类中添加Classes的字段classses
2.修改ClassesMapper.xml:
<mapper namespace="com.wzj.dao.IClassesDao">
<resultMap type="com.wzj.entity.Classes" id="classesMap">
<id property="id" column="c_id" />
<result property="name" column="c_name" />
<!-- 映射结果中的Teacher对象
property:字段名称
javaType:要映射的类型的完整名称或者别名
-->
<association property="teacher" javaType="com.wzj.entity.Teacher">
<id property="id" column="t_id" />
<result property="name" column="t_name" />
<!-- 这里要再嵌套映射Teacher类中的Classes对象 -->
<association property="classes" column="teacher_id" select="com.wzj.dao.IClassesDao.selectClassesById" />
</association>
</resultMap>
<select id="selectClassesById" resultMap="classesMap">
select * from classes c,teacher t where c.teacher_id=t.t_id and c.c_id=#{id}
</select>
</mapper>3.TeacherMapper.xml中:
<mapper namespace="com.wzj.dao.ITeacherDao">
<resultMap type="com.wzj.entity.Teacher" id="teacherMap">
<id property="id" column="t_id" />
<result property="name" column="t_name" />
<association property="classes" column="t_id"
select="com.wzj.dao.IClassesDao.selectClassesById" />
</resultMap>
<select id="selectTeacherById" resultMap="teacherMap">
select * from teacher where t_id=#{id}
</select>
</mapper>注意:在这里的话,association元素中的column要写t_id了,因为映射结果中没有teacher_id一列
4.运行测试类,成功输出结果.
以上就是单向和双向的一对一关联关系,总的来说,使用嵌套的select方式,会引起N+1查询的问题,因为它会根据Classes中的每一个记录再访问数据,这样频繁的访问数据势必会导致系统性能的下降,关于N+1查询问题,能力有限,就不阐述了,感兴趣的童鞋可以百度一下。
本文详细介绍了在MyBatis中处理一对一关联映射的方法,包括单向和双向映射。通过示例展示了如何使用嵌套ResultMap和嵌套Select方式,涉及Classes与Teacher类的关系配置。同时提到了N+1查询问题及其性能影响。
352

被折叠的 条评论
为什么被折叠?



