Mybatis笔记(四):多对一的处理
时间:2021/10/14
一.目的
这次我们构建的数据库表中存在多对一的关系,也就是多个学生对应一个老师。我们的目的是为了完成类似下面这种多表查询的操作:
1 SELECT * FROM student s, teacher t WHERE s.tid = t.id;
查询效果如下:
以下是为了完了完成这种多对一关系的多表查询所需的准备工作和实际操作:
二.创建数据库中相应的表
这里我们在mybatis数据库中新建了两张表,分别是teacher表和student表,表中内容具体如下:
要注意student表中的tid列作为外键与teacher表中的id列绑定。
三.编写实体类
Teacher.class:
1 package bupt.machi.pojo; 2 3 public class Teacher { 4 5 private int id; 6 private String name; 7 8 public int getId() { 9 return id; 10 } 11 12 public String getName() { 13 return name; 14 } 15 16 public void setId(int id) { 17 this.id = id; 18 } 19 20 public void setName(String name) { 21 this.name = name; 22 } 23 24 @Override 25 public String toString() { 26 return "Teacher{" + 27 "id=" + id + 28 ", name='" + name + '\'' + 29 '}'; 30 } 31 }
Student.class:
1 package bupt.machi.pojo; 2 3 public class Student { 4 5 private int id; 6 private String name; 7 //要注意这里不要写tid,要写对象teacher,体现一对多,自己并不是很理解 8 //可能是为了简化后面的操作 9 private Teacher teacher; 10 11 public int getId() { 12 return id; 13 } 14 15 public String getName() { 16 return name; 17 } 18 19 public Teacher getTeacher() { 20 return teacher; 21 } 22 23 public void setId(int id) { 24 this.id = id; 25 } 26 27 public void setName(String name) { 28 this.name = name; 29 } 30 31 public void setTeacher(Teacher teacher) { 32 this.teacher = teacher; 33 } 34 35 @Override 36 public String toString() { 37 return "Student{" + 38 "id=" + id + 39 ", name='" + name + '\'' + 40 ", teacher=" + teacher + 41 '}'; 42 } 43 }
要注意上面中属性teacher是一个对象,而不是数据库表中的tid,这位了更好的体现多对一的关系。
四.编写接口
StudentMapper.xml:
1 package bupt.machi.dao; 2 3 import bupt.machi.pojo.Student; 4 5 import java.util.List; 6 7 public interface StudentMapper { 8 9 List<Student> getStudent(); 10 }
TeacherMapper.xml:
1 package bupt.machi.dao; 2 3 import bupt.machi.pojo.Teacher; 4 import org.apache.ibatis.annotations.Param; 5 import org.apache.ibatis.annotations.Select; 6 7 public interface TeacherMapper { 8 9 // @Select("select * from mybatis.teacher where id = #{tid}") 10 Teacher getTeacherById(@Param("tid") int id); 11 }
五.编写Mapper配置文件
之后我们会将Mapper配置文件放在resouces文件夹中,这样可以方便不同类型的文件之间的分离,但是要注意该配置文件的路径要和对应接口的路径一致,在resources中要用/,而不是Java包中的.来分隔。
1)首先写一种结果不对的配置文件写法:
1 <?xml version="1.0" encoding="UTF8" ?> 2 <!DOCTYPE mapper 3 PUBLIC "-//mybatis.org//DTD Config 3.0//EN" 4 "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 5 <!--绑定接口--> 6 <mapper namespace="bupt.machi.dao.StudentMapper"> 7 <select id="getStudent" resultType="Student"> 8 select * from student 9 </select> 10 11 </mapper>
当使用上面这种写法时,测试类运行出来的结果如下:
这是因为数据库中查出来的tid与实体类中的Teacher属性无法对应,导致了值为null情况的出现。
2)正确的配置文件写法
- 第一种方法:按照查询嵌套处理,类似于子查询
1 <?xml version="1.0" encoding="UTF8" ?> 2 <!DOCTYPE mapper 3 PUBLIC "-//mybatis.org//DTD Config 3.0//EN" 4 "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 5 <!--绑定接口--> 6 <mapper namespace="bupt.machi.dao.StudentMapper"> 7 <select id="getStudent" resultMap="student"> 8 select * from student 9 </select> 10 11 <!-- 这里的type是来说明结果的类型,本质上还是Student类型的 --> 12 <resultMap id="student" type="Student"> 13 <!-- 复杂的属性需要单独处理 14 对象:association 15 集合:collection 16 --> 17 <!-- 由于属性teacher是一个对象,需要用javaType说明他的类,使用select指定的查询给他赋值 --> 18 <association property="teacher" column="tid" javaType="teacher" select="getTeacherById"/> 19 </resultMap> 20 21 <select id="getTeacherById" resultType="teacher"> 22 select * from teacher where id = #{tid} 23 </select> 24 </mapper>
具体讲解见注释,查询结果如下:
- 第二种方法:按照结果嵌套处理,类似于联表查询
<select id="getStudent2" resultMap="student2"> select s.id sid, s.name sname, t.id tid, t.name tname from student s, teacher t where s.tid = t.id; </select> <resultMap id="student2" type="Student"> <result property="id" column="sid"/> <result property="name" column="sname"/> <association property="teacher" javaType="Teacher"> <result property="id" column="tid"/> <result property="name" column="tname"/> </association> </resultMap>
查询结果如下:
努力,向上,自律