当前位置: 首页 > 工具软件 > Mybatis-Link > 使用案例 >

MyBatis级联查询

狄玉书
2023-12-01

MyBatis级联查询

简介

级联关系是一个数据库实体的概念,有 3 种级联关系,分别是一对一级联、一对多级联以及多对多级联。例如,一个角色可以分配给多个用户,也可以只分配给一个用户。大部分场景下,我们都需要获取角色信息和用户信息,所以会经常遇见以下 SQL。

在级联中存在 3 种对应关系。
一对一的关系:如一个学生对应一个学号,学生与学号就是典型的一对一关系。
一对多的关系,如学生和班级的关系。通俗的理解就是,一个班级里可以有很多学生。
多对多的关系,学生和职务的关系,一个学生可以有多个职务,一个职务也可以多个人。

一对一

在 MyBatis 中,通过 元素的子元素 处理一对一级联关系。示例代码如下。

<association property="studentCard" column="cardId"
            javaType="net.biancheng.po.StudentCard"
            select="net.biancheng.mapper.StudentCardMapper.selectStuCardById" />
  • property:指定映射到实体类的对象属性。
  • column:指定表中对应的字段(即查询返回的列名)。
  • javaType:指定映射到实体对象属性的类型。
  • select:指定引入嵌套查询的子 SQL 语句,该属性用于关联映射中的嵌套查询。
创建数据库初始数据
#学号表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;
}
创建Mapper类及XML

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);
}
提供两次方式xml进行查询,代码均在StudentMapper .xml
分步查询

分两步查询两张表

<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" />
  • property:指定映射到实体类的对象属性。
  • column:指定表中对应的字段(即查询返回的列名)。
  • javaType:指定映射到实体对象属性的类型。
  • select:指定引入嵌套查询的子 SQL 语句,该属性用于关联映射中的嵌套查询。
创建数据库初始数据
#新建班级表
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;
mapper
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>
 类似资料: