分析模型
还是沿用前面学生和老师的例子
前面我们讨论的是多对一的关系,即在获取学生全部信息的同时获取他的老师的信息
- 【学生】多个学生 关联 一个老师【多对一】
- 【老师】一个老师 集合/管理/掌管 多个学生【一对多】
环境搭建
和多对一的环境搭建一样,我们创建一个新项目MyBatis-07
老步骤:粘贴上一个项目中可以重用的资源
- 前面我们在mapper接口和mapper.xml文件中写的都是多对一的操作,现在要进行一对多的操作,所以需要将这些文件清理干净
代码编写
1.简化模型
- 为了简化我们的操作,我们修改一下Student这个POJO的定义,将其teacher属性修改为和数据库中一样的int tid
package com.thhh.pojo; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @Data @AllArgsConstructor @NoArgsConstructor public class Student { private int id; private String name; private int tid; }
- 通过前面的分析,一个老师管理多个学生,所以Teacher这个POJO的定义需要增加一个List集合
package com.thhh.pojo; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import java.util.List; @Data @AllArgsConstructor @NoArgsConstructor public class Teacher { private int id; private String name; private List<Student> studentList; }
- 测试
package com.thhh.dao; import com.thhh.pojo.Teacher; import com.thhh.utils.MyBatisUtils; import org.apache.ibatis.session.SqlSession; import org.junit.Test; import java.util.List; public class TestMapper { @Test public void testGetTeacherList(){ SqlSession sqlSession = MyBatisUtils.getSqlSession(); TeacherMapper mapper = sqlSession.getMapper(TeacherMapper.class); List<Teacher> teacherList = mapper.getTeacherList(); for (Teacher teacher : teacherList) { System.out.println(teacher); } sqlSession.close(); } }
我们可以发现上面的数据虽然查询出来了,但是对象的studentList属性值为NULL,所以我们的一对多要解决的问题,也是属性名和数据库字段不一致导致的属性为NULL的问题
2.解决问题
其实解决问题的办法和原来差不多,对于复杂属性,我们的解决办法就一个——使用resultMap
- 对象的对象属性我们使用association来映射/赋值
- 对象的集合属性使用collection节点来映射/赋值
照猫画虎,只是需要修改两个地方,其他的都是一样的
①将复杂属性映射节点改为collection
②将原来的javaType改为ofType,原因:collection表示集合,使用集合我们需要指的的不是Java类型,而是集合的泛型;而原来的对象属性,我们就需要指定返回的Java类型
<?xml version="1.0" encoding="UTF8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.thhh.dao.TeacherMapper">
<select id="getTeacher" resultMap="TeacherMap">
SELECT s.id sid,s.name sname,t.id tid,t.name tname
FROM student s,teacher t
WHERE s.tid = t.id AND t.id = #{tid}
</select>
<resultMap id="TeacherMap" type="Teacher">
<result property="id" column="tid"/>
<result property="name" column="tname"/>
<!--对象复杂属性我们使用association来映射/赋值
集合属性使用collection节点来映射/赋值-->
<collection property="studentList" ofType="Student">
<result property="id" column="sid"/>
<result property="name" column="sname"/>
<result property="tid" column="tid"/>
</collection>
</resultMap>
</mapper>
可见,我们将这个老师对应的学生集合查询出来了
3.JavaType和ofType的区别
JavaType和ofType都是用来指定对象类型的,但是JavaType是用来指定pojo中属性的类型,而ofType指定的是映射到list集合属性中pojo的类型
各自的使用场景:链接: link.
在实际的测试中可以发现
- 只要复杂属性是类属性,我们就使用association来映射,并且使用javatype指定映射的Java类的类型,即POJO;
- 只要复杂属性是List集合属性,我们就使用collection来映射,并且使用oftype指定List集合中存储的对象类型,即List<?>的泛型
4.小结
-
关联 - association 【多对一】
-
集合 - collection【一对多】
-
javaType 和 ofType
-
注意点
- 保证编写的SQL的可读性,保证通俗易懂
- 注意一对多和多对一中属性名和数据表中字段名不一致的时候的处理(这个问题就是学习一对多和多对一的重点)
- 如果遇到不好排查的BUG,可以使用日志,推荐使用log4j,因为log4j可以生成日志文件,而我们的标准日志只能在控制台输出,不能保存
5.面试高频(自己找文章看会)
- MYSQL引擎
- INNODB的底层原理
- 索引
- 索引优化