文章目录
一、创建表结构,添加数据,实现表中数据的关联关系
-
数据的关联关系:
-
一个班级中,有多名学生,一个班主任以及其他很多科任教师
-
对于学生而言,多个学生,关联一个班主任,每个学生都和班主任有着关联关系 --【多对一】
-
班级中,有一名学生上课睡觉,被班主任抓个正着,拎出来训话 --【一对一】
-
对于班主任而言,一个班主任管理着一个班级,而班级中有很多学生 --【一对多】
-
一个班级中的每天都有不同的课程,不同的课程对应不同的教师 --【多对多】
-
-
- 表结构搭建
-- 创建教师表 CREATE TABLE IF NOT EXISTS `teacher` ( `id` int(10) NOT NULL, `name` varchar(30) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; --新增一名教师 INSERT INTO `teacher` (`id`, `name`) VALUES (1, '柳神'); ----------------------------------------------------------------- --创建学生表 CREATE TABLE IF NOT EXISTS `student` ( `id` int(10) NOT NULL, `name` varchar(30) DEFAULT NULL, `tid` int(10) DEFAULT NULL, PRIMARY KEY (`id`), KEY `fktid` (`tid`), CONSTRAINT `fktid` FOREIGN KEY (`tid`) REFERENCES `teacher` (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; --新增学生 INSERT INTO `student` (`id`, `name`, `tid`) VALUES(1, '楚风', 1),(2, '龙大宇', 1),(3, '姬大德', 1),(4, '石昊', 1),(5, '叶凡', 1);
二、 association 标签:用于一对一、多对一场景使用
-
association 标签属性:
-
property :配置实体类属性名
-
javaType :指定封装结果的类型。当使用 select 属性时,无需指定关联的类型,结果会直接封装到调用的查询语句中
-
column :配置数据库列名,搭配 select 属性使用,从第一条 SQL 中获取当前指定字段的内容,在将该内容传入 select 属性调用的 SQL 中
-
select :使用另一个select查询封装的结果。当使用该属性时,无需配置实体类与数据库之间的映射关系
-
-
association 标签的子标签:< id >,< result >, 作用和 resultMap 标签的子标签一致
1、实现一对一,多对一关系结果集映射
实现联表查询的方式有两种,一种是按照查询嵌套处理,一种是按照结果嵌套处理。通常来讲按照结果嵌套处理比较灵活,代码看起来也更加简洁。
1.1 按照查询嵌套处理
该方式的执行流程:先执行第一个被调用的 < select > 标签语句,查询出结果后通过 < association > 标签的 column 获取结果中指定字段的值,在通过 select 调用第二个 < select > 标签语句 ,将 column 获取到的值传入该标签语句中,实现类似于子查询的操作,最后将第一个被调用的标签语句查询出的结果封装到 < resultMap > 的 type 属性当中,将第二个被调用的标签语句封装到 < association > 标签的 property 所指定的实体类属性当中,以此来实现结果集的映射。
-
根据表创建对应的实体类
-
创建 Student 实体
@Alias("Student") // 引用 mybatis-config.xml 中的实体类路径别名,这样再次引用时候直接引用别名就可以找到全路径了 @Data // 自动生成 get()、set()等方法 public class Student { private Integer id; private String name; private String tid; // 关联教师实体,形成一对一,多对一的关联关系,将查询结果封装到该属性中 private Teacher teacher; }
-
创建 Teacher 实体
@Data @Alias("Teacher") public class Teacher { private Integer id; private String name; }
-
创建 StudentMapper
public interface StudentMapper { List<Student> getStudent(); }
-
创建 XML
<select id="getStudent" resultMap="StudentMap"> select * from student </select> <resultMap id="StudentMap" type="Student"> <result column="id" property="id"/> <result column="name" property="name"/> <!-- 查询完第一条查询SQL之后,通过association标签的column属性获取对应字段的值,将该值传入select属性所指定的查询SQL中, 根据条件查询完之后将结果封装到property属性所指定的实体bean的属性中。 --> <association property="teacher" column="tid" select="getTeacher"/> </resultMap> <select id="getTeacher" resultType="Teacher"> select * from teacher where id = #{tid} </select>
-
代码运行结果
-
1.2 按照结果嵌套处理(推荐)
直接使用多表联查的形式去查询数据,通过 result 标签的属性将 SQL 语句中的字段和实体类形成映射关系,再通过 association 标签的 property 属性将 Teacher 实体中的 name 属性与 Student 实体的 teacher 属性值形成映射,以此来完成返回值映射。
-
实体类不变,StudentMapper 接口中新增查询方法
public interface StudentMapper { List<Student> getStudent(); List<Student> getStudentAndTeacher(); }
-
XML
<resultMap id="StudentAndTeacher" type="Student"> <result property="id" column="id"/> <result property="name" column="name"/> <!-- 将查询结果映射到 Teacher 实体类中 --> <association property="teacher" javaType="Teacher"> <result property="name" column="name"/> </association> </resultMap> <select id="getStudentAndTeacher" resultMap="StudentAndTeacher"> select s.id as 学生编号, s.name as 学生姓名, s.tid as 班级编号, t.id as 教师编号,t.name as 教师姓名 from student s, teacher t where s.tid = t.id </select>
-
运行结果:
三、 collection 标签:用于一对多、多对多场景使用(实体里放集合)
-
collection 标签属性:
-
property :实体类属性名
-
select :使用另一个select查询封装的结果。当使用该属性时,便不需要在配置实体类与数据库之间的映射关系了
-
column :为数据库中的列名,与select配合使用
-
ofType :指定集合中的泛型信息
-
-
collection 标签的子标签:< id >,< result >, 作用和 resultMap 标签的子标签一致
1、实现一对多,多对多关系结果集映射
1.1 按照查询嵌套处理
该方式的执行流程和 association 大致相同,区别为,association 是通过学生共有的班级编号匹配班主任的教师编号,是多对一的关系。而 collection 是通过教师编号去匹配班级编号相同的学生,是一对多关系。
-
根据表创建对应的实体类
-
创建 Student 实体
@Alias("Student") @Data public class Student { private Integer id; private String name; private String tid; }
-
创建 Teacher 实体
@Data @Alias("Teacher") public class Teacher { private Integer id; private String name; // 实现老师对应学生的 一对多关联关系 private List<Student> student; }
-
创建 TeacherMapper
public interface TeacherMapper { //通过教师编号查询与之关联的学生 List<Teacher> getManyToOne(int id); }
-
创建 XML
<select id="getManyToOne" resultMap="getManyToOne"> select * from teacher where id = #{id} </select> <resultMap id="getManyToOne" type="Teacher"> <result property="id" column="id"/> <result property="name" column="name"/> <collection property="student" javaType="ArrayList" select="getStudent" column="id"/> </resultMap> <select id="getStudent" resultType="Student"> select * from student where tid = #{id} </select>
-
代码运行结果
-
1.2 按照结果嵌套处理(推荐)
-
实体类不变,TeacherMapper 接口中新增查询方法
public interface TeacherMapper { List<Teacher> getManyToOne(int id); List<Teacher> getManyToOne2(int id); }
-
XML
<resultMap id="getManyToOne2" type="Teacher"> <result property="id" column="id"/> <result property="name" column="name"/> <collection property="student" ofType="Student"> <result column="id" property="id"/> <result column="name" property="name"/> <result column="tid" property="tid"/> </collection> </resultMap> <select id="getManyToOne2" resultMap="getManyToOne2"> select s.id sid,s.name sname,t.name tname,t.id,tid from student s,teacher t where s.tid = t.id and t.id = #{tid} </select>
-
运行结果: