其实不管是一对一映射还是一对多映射关系,在处理关联对象的时候都有两种方式,即使用嵌套的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" parameterType="int" 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>
- 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();
- }
在一条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>
- <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查询问题,能力有限,就不阐述了,感兴趣的童鞋可以百度一下。