级联关系是一个数据库实体的概念,有 3 种级联关系,分别是一对一级联、一对多级联以及多对多级联。例如,一个角色可以分配给多个用户,也可以只分配给一个用户。大部分场景下,我们都需要获取角色信息和用户信息,所以会经常遇见以下 SQL。
在级联中存在 3 种对应关系。
一对一的关系:如一个学生对应一个学号,学生与学号就是典型的一对一关系。
一对多的关系,如学生和班级的关系。通俗的理解就是,一个班级里可以有很多学生。
多对多的关系,学生和职务的关系,一个学生可以有多个职务,一个职务也可以多个人。
在 MyBatis 中,通过 元素的子元素 处理一对一级联关系。示例代码如下。
<association property="studentCard" column="cardId"
javaType="net.biancheng.po.StudentCard"
select="net.biancheng.mapper.StudentCardMapper.selectStuCardById" />
#学号表DDL
CREATE TABLE `student_card` (
`id` int NOT NULL AUTO_INCREMENT,
`student_id` int DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `student_id` (`student_id`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8;
#插入学号表数据
insert into `student_card`(`id`,`student_id`) values (1,20200311),(2,20200314),(3,20200709),(4,20200508),(5,20207820);
#学生表DDL
CREATE TABLE `student_card` (
`id` int NOT NULL AUTO_INCREMENT,
`name` varchar(20) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,
`sex` tinyint DEFAULT NULL,
`card_id` int DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `card_id` (`card_id`),
CONSTRAINT `student_ibfk_1` FOREIGN KEY (`card_id`) REFERENCES `student_card` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;
#插入学生表数据
insert into `student`(`id`,`name`,`sex`,`card_id`) values (1,'张三',0,1),(2,'李四',0,2),(3,'王五',1,3),(4,'赵六',0,4),(5,'钱七',1,5),(6,'孙八',0,NULL);
Student 学生类
@Data
public class Student {
private int id;
private String name;
private int sex;
//学号表
private StudentCard studentCard;
}
StudentCard 学号类
@Data
public class StudentCard {
private int id;
private int studentId;
}
StudentCardMapper类
public interface StudentCardMapper {
public StudentCard selectStuCardById(int id);
}
StudentCardMapper.xml
<mapper namespace="net.biancheng.mapper.StudentCardMapper">
<!-- 根据id查询学号信息-->
<select id="selectStuCardById"
resultType="net.biancheng.po.StudentCard">
SELECT * FROM student_card WHERE id = #{id}
</select>
</mapper>
StudentMapper 类
public interface StudentMapper {
public Student selectStuById(int id);
}
分两步查询两张表
<mapper namespace="net.biancheng.mapper.StudentMapper">
<!-- 一对一根据id查询学生信息:级联查询的第一种方法(嵌套查询,执行两个SQL语句) -->
<resultMap type="net.biancheng.po.Student" id="cardAndStu">
<id property="id" column="id" />
<result property="name" column="name" />
<result property="sex" column="sex" />
<!-- 一对一级联查询 -->
<association property="studentCard" column="card_id"
javaType="net.biancheng.po.StudentCard"
select="net.biancheng.mapper.StudentCardMapper.selectStuCardById" />
</resultMap>
<select id="selectStuById" parameterType="Integer"
resultMap="cardAndStu">
select * from student where id=#{id}
</select>
</mapper>
一次性查询两张表
<resultMap type="net.biancheng.po.Student" id="cardAndStu">
<id property="id" column="id" />
<result property="name" column="name" />
<result property="sex" column="sex" />
<!-- 一对一级联查询 -->
<association property="studentCard"
javaType="net.biancheng.po.StudentCard">
<id property="id" column="id" />
<result property="studentId" column="student_id" />
</association>
</resultMap>
<select id="selectStuById" parameterType="Integer"
resultMap="cardAndStu">
SELECT s.*,sc.student_id FROM student s,student_card sc
WHERE
s.card_id = sc.id AND s.id=#{id}
</select>
在 MyBatis 中,通过 元素的子元素 处理一对多级联关系,collection 可以将关联查询的多条记录映射到一个 list 集合属性中。示例代码如下。
<collection property="studentList"
ofType="net.biancheng.po.Student " column="classId"
select="net.biancheng.mapper.StudentMapper.selectStudentByClassId" />
#新建班级表
CREATE TABLE `class` (
`id` int NOT NULL,
`class_name` varchar(255) COLLATE utf8_bin DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
#新建学生表
ALTER TABLE student ADD class_id INT(11) AFTER id
package net.biancheng.po;
import java.util.List;
//班级
@Data
public class Class{
private int id;
private String className;
private List<Student> studentList;
}
//学生表添加班级字段
private int classId;
public interface StudentMapper {
//StudentMapper里添加根据班级id查询学生列表方法
public List<Student> selectStudentByClassId(int classId);
}
<!-- 根据班级id查询学生列表 -->
<select id="selectStudentByClassId" resultType="net.biancheng.po.Student"
parameterType="Integer">
SELECT * FROM `student` where class_id=#{id}
</select>
public interface ClassMapper {
/**
*查询
*/
public Class selectClassById(int id);
}
<!-- ClassMapper.xml -->
<!-- 一对多 根据id查询班级及其关联的学生信息:级联查询的第一种方法(分步查询) -->
<resultMap type="net.biancheng.po.Class" id="classAndUser">
<id property="id" column="id" />
<result property="className" column="class_name" />
<!-- 一对多级联查询,ofType表示集合中的元素类型,将id传递给selectStudentByClassId-->
<collection property="studentList"
ofType="net.biancheng.po.Student" column="id"
select="net.biancheng.mapper.StudentMapper.selectStudentByClassId" />
</resultMap>
<select id="selectClassById" parameterType="Integer"
resultMap="classAndUser">
select * from class where id=#{id}
</select>
<!-- ClassMapper.xml -->
<!-- 一对多 根据id查询用户及其关联的订单信息:级联查询的第二种方法(单步查询) -->
<resultMap type="net.biancheng.po.Class" id="classAndUser">
<id property="id" column="id" />
<result property="className" column="class_name" />
<!-- 一对多级联查询,ofType表示集合中的元素类型,将id传递给selectOrderById -->
<collection property="studentList"
ofType="net.biancheng.po.Student" column="id"
select="net.biancheng.mapper.StudentMapper.selectStudentByClassId" />
</resultMap>
<select id="selectClassById" parameterType="Integer"
resultMap="classAndUser">
select * from class where id=#{id}
</select>