复杂环境(一对多,多对一)实现
- 一对多
- 多对一
多个学生和一个老师的问题
不同的角度分析问题,
-
对于学生而言,关联,多个学生关联一个老师(多对一)
-
对于老师而言,集合,一个老师,有多个学生(一对多 )
在resultMap设置中还有其余一些设置
- association 一个复杂类型的关联
- collection 一个复杂类型的集合
环境搭建
-
添加student表和teacher表
- [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SgZSfBdQ-1597762948536)(…/…/…/AppData/Roaming/Typora/typora-user-images/image-20200818150653053.png)]
- 要设置外键
-
-
模块结构
-
实体类、实体类接口,接口映射xml文件,核心配置文件、工具类
-
实体类
-
@Data @AllArgsConstructor @NoArgsConstructor public class Student { private int id; private String name; private Teacher teacher; }
-
实体类映射接口
-
public interface TeacherMapper { @Select("select * from teacher where id = #{tid}") List<Teacher> getTeacher(@Param("tid") int id); }
-
mapper.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"> <!--命名空间--> <mapper namespace="com.haoyun.dao.TeacherMapper"> </mapper>
-
核心配置文件
-
<mappers> <mapper resource="StudentMapper.xml"/> <mapper resource="TeacherMapper.xml"/> </mappers>
-
简单测试
-
@Test public void teacher(){ SqlSession sqlSession = MybatisUtils.getSqlSession(); TeacherMapper mapper = sqlSession.getMapper(TeacherMapper.class); List<Teacher> teacher = mapper.getTeacher(2); for (Teacher teacher1 : teacher) { System.out.println(teacher1); } sqlSession.close(); }
-
-
多对一的处理
- sql可以直接写出来,
select * from student,teacher where teacher.id=student.tid
有两种形式:
- 按照查询嵌套处理
- 按照结果嵌套处理
如何写入方法思路:
- 查询所有学生信息
- 根据查询出来的学生的tid,寻找对应的老师寻找对应的老师
解决问题,主要流程:
- JavaBean类设置别名好操作
- 编写mapper.xml文件
- 使用resultMap的association设置
- 注册核心文件
- 测试
按照查询嵌套处理
-
设置别名
-
@Data @AllArgsConstructor @NoArgsConstructor @Alias("Student") public class Student { private int id; private String name; private Teacher teacher; }
-
@Data @AllArgsConstructor @NoArgsConstructor @Alias("Teacher") public class Teacher { private int id; private String name; }
-
-
编写mapper.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"> <mapper namespace="com.haoyun.dao.StudentMapper"> <resultMap id="StudentTeacher" type="Student"> <!--映射名称 返回值类型--> <!-- <result property="name" column="name"/>--> <!--属性名和字段名同名的可以不用写了--> <!--association 关联--> <!--collection 集合--> <association property="teacher" column="tid" javaType="Teacher" select="getTeacher"/> <!--这里的property是一个对象,通过tid不能直接获取,javaType设置这个对象的类型,然后加入一个查询getTeacher--> </resultMap> <select id="getStudent" resultMap="StudentTeacher"> select * from student </select> <select id="getTeacher" resultType="Teacher"> <!--这个子查询的#引用因为只有一个,所以名字随便写也会自动匹配--> select * from teacher where id =#{id} </select> </mapper>
-
有点类似子查询,按照查询嵌套处理
-
-
添加核心配置文件映射
-
<mappers> <mapper resource="StudentMapper.xml"/> <mapper resource="TeacherMapper.xml"/> </mappers>
-
-
测试
-
@Test public void teacher(){ SqlSession sqlSession = MybatisUtils.getSqlSession(); StudentMapper mapper = sqlSession.getMapper(StudentMapper.class); List<Student> student = mapper.getStudent(); for (Student student1 : student) { System.out.println(student1); } sqlSession.close(); }
-
-
按照结果嵌套处理
-
嵌套处理
-
<resultMap id="StudentTeacher2" type="Student"> <result property="id" column="sid"/> <result property="name" column="sname"/> <association property="teacher" javaType="Teacher"> <!--在Student,javaBean中,教师是用属性名teacher的,类型为Teacher,这里面嵌套一个结果集映射--> <result property="name" column="tname"/> </association> </resultMap> <select id="getStudent2" resultMap="StudentTeacher2"> select s.id sid,s.name sname,t.name tname from teacher t,student s where s.tid = t.id; </select>
-
-
测试
- 结果是一样的
-
总结:
- 多对一查询方式主要也就两种
- 子查询
- 联表查询
- 多对一查询方式主要也就两种
一对多的处理
- 重点就是在配置TeacherMapper.xml上
-
编写JavaBean
-
@Data @AllArgsConstructor @NoArgsConstructor @Alias("Teacher") public class Teacher { private int id; private String name; private List<Student> students; }
-
一个老师对应多个学生,学生是一个集合用list装起来
-
@Data @AllArgsConstructor @NoArgsConstructor @Alias("Student") public class Student { private int id; private String name; private int tid; }
-
学生的一些属性
-
-
编写TeacherMapper.xml文件时要先理清关系,要做的是个一个老师有哪些学生,所以先定位哪个老师
-
-
这样就能查出老师id为1的老师有哪些学生
-
-
需要传递一个老师对应的id
-
所以编写接口的时候需要传递id
-
List<Teacher> getTeacherById(@Param("id")int id);
-
<mapper namespace="com.haoyun.dao.TeacherMapper"> <resultMap id="TeacherStudent" type="Teacher"> <result property="id" column="tid"/> <result property="name" column="tname"/> <collection property="students" ofType="Student"> <result property="id" column="sid"/> <result property="name" column="sname"/> <result property="tid" column="tid"/> </collection> </resultMap> <select id="getTeacherById" resultMap="TeacherStudent"> select s.id sid,s.name sname,t.name tname,t.id tid from teacher t,student s where s.tid=t.id and t.id = #{id} </select> </mapper>
-
因为这条select语句采用了很多别名,所以编写map的时候需要多加几个结果集映射
-
这是按照结果嵌套来处理的
-
-
按照查询嵌套
-
<select id="getTeacherById2" resultMap="TeacherStudent2"> select * from teacher where id = #{id} </select> <resultMap id="TeacherStudent2" type="Teacher"> <collection property="students" javaType="ArrayList" ofType="Student" select="student" column="id"/> </resultMap> <select id="student" resultType="Student"> select * from student where tid = #{id} </select>
-
查询嵌套,先查询一个再查询一个
小结:
- 关联 association(多对一)
- 集合 collection(一对多)
- javaType & ofType
- javaType 用来指定实体类中属性的类型
- ofType 用来指定映射到List或者集合中的POJO类型(List),泛型中的约束类型
- 注意点
- 保证sql的可读性
- 注意属性名和字段问题
- 使用日志好进行错误排查,建议使用LOG4J
慢SQL,比较慢,就是少自己写,多搜集点效率高的sql语句,到时遇到了直接用
面试高频:
- Mysql引擎
- InnoDB底层原理
- 索引
- 索应优化