MyBatis学习(一)之一对一关联映射查询

本文详细介绍了在MyBatis中处理一对一关联映射的方法,包括单向和双向映射。通过示例展示了如何使用嵌套ResultMap和嵌套Select方式,涉及Classes与Teacher类的关系配置。同时提到了N+1查询问题及其性能影响。

           最近正在学习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查询问题,能力有限,就不阐述了,感兴趣的童鞋可以百度一下。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值