10、多对一处理

本文详细介绍了在MyBatis中如何处理多对一和一对多的关系映射,通过具体的JavaBean和Mapper配置展示了查询嵌套处理和结果嵌套处理两种方式,实现学生与老师关系的查询。测试结果显示,两种方式都能正确地获取每个学生及其关联的老师信息。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在这里插入图片描述

  • 多个学生,对应一个老师
  • 对于学生而言,关联…多个学生,关联一个老师**【多对一】**
  • 对于老师而言,集合…一个老师,有多个学生**【一对多】**

10.1、按照查询嵌套处理

现在有一个需求,建立多个学生和老师间的关系,我们进行查询所有学生信息,包括学生的老师信息。

Teacher Bean

@Data
public class Teacher {
    private int id;
    private String name;
}

Student Bean

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Student {

    private int id;
    private String name;
    //学生需要关联一个老师
    private Teacher teacher;
}

TeacherMapper 接口

public interface TeacherMapper {
    Teacher getOneTeacher(int id);
}

StudentMapper 接口

public interface StudentMapper {
    //查询所有学生的信息,以及对应的老师
    List<Student> getAllStudent();
}

TeacherMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.johngea.mapper.TeacherMapper">
    <select id="getOneTeacher" resultType="Teacher">
        select * from teacher where id = #{id}
    </select>
</mapper>

StudentMapper.xml

在原来的项目中使用 resultMap ,对于单个属性,只需要添加一个 <result property="" column=""/> ,但此处,Student 类中有一个 Teacher 属性,而 Teacher 属性又包含多个属性,因此 result 在此处并不适用。

reslutMap 中,还有以下标签:

  • association (关联)
  • collection (集合)

前面我们说过,对于学生而言,关联…多个学生,关联一个老师**【多对一】**,因此,此处我们应该用到association(关联)

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.johngea.mapper.StudentMapper">
    <!--思路:
            1.查询所有的学生
            2.根据查询出来的学生的tid,寻找对应的老师
    -->
    <!--第1步-->
    <select id="getAllStudent" resultMap="StudentsTeacher">
        select * from student
    </select>
    <!--设定对应属性-->
    <resultMap id="StudentsTeacher" type="Student">
        <association property="teacher" column="tid" javaType="Teacher" select="getOneTeacher" />
    </resultMap>
    <!--第2步-->
    <select id="getOneTeacher" resultType="Teacher">
        select * from teacher where id = #{id}
    </select>
</mapper>

association 标签中,和 result 标签一样,有 property和column 属性,前面在学 resultMap 时,我们说过 property 是对应 JavaBean 中的属性, column 则对应的是数据库中的字段,而在数据库中 student 表是通过 tid 字段去查询对应的 teacher 。因此,在association 中,property 对应的应该是 Student 类中的 teacher 属性,而 column 对应的是数据库中 student 表的 tid 字段。

select: 仅仅做完对应关系是不够的,我们在代码中分析过,查对应老师前还需要先查询所有学生,根据查到学生的tid在去查对应的老师,所以我们还要用到嵌套查询,将查询老师的操作包含在查询在所有学生中,而 association 中有 select 属性可以帮我们完成这一步。

javaType: 查询完成后,需要将查询结果封装为一个对象,因为property 中的teacher是一个对象,需要给该对象设置类型赋值,因此由javaType完成该操作。

Test

@Test
public void getAllStudent(){
    SqlSession sqlSession = MybatisUtils.getSqlSession();
    StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
    List<Student> students = mapper.getAllStudent();
    for (Student student : students) {
        System.out.println(student);
    }
    sqlSession.close();
}

运行结果

Student(id=1, name=小明, teacher=Teacher(id=1, name=秦老师))
Student(id=2, name=小红, teacher=Teacher(id=1, name=秦老师))
Student(id=3, name=小张, teacher=Teacher(id=1, name=秦老师))
Student(id=4, name=小李, teacher=Teacher(id=1, name=秦老师))
Student(id=5, name=小王, teacher=Teacher(id=1, name=秦老师))

这种方式就类似于这样写 sql 语句:

select s.id,s.name,t.name from student s,teacher t where tid = (select id from teacher)

通过 sql 语句可以看出,这是一种嵌套子查询的方式。

10.2、按结果嵌套处理

StudentMapper.xml

<!--方式2.按照结果进行处理-->
<select id="getAllStudent2" resultMap="StudentsTeacher2">
    select s.id sid,s.name sname,t.id tid,t.name tname from student s, teacher t where s.tid = t.id
</select>
<!--先对Student进行处理-->
<resultMap id="StudentsTeacher2" type="Student">
    <!--id对应Student类中的id, sid对应sql语句中的sid-->
    <result property="id" column="sid"/>
    <!--name对应Student类中的name, sname对应sql语句中的name-->
    <result property="name" column="sname"/>
    <!--由于teacher在Student类中是一个属性, 而Teacher又有自己的属性, 我们需要再对Teacher进行单独处理,但是要将其设置为Teacher类型,因为其是属于Student类的属性-->
    <association property="teacher" javaType="Teacher">
        <!--这里的id对应Teacher类中的id, tid对应sql语句中的tid-->
        <result property="id" column="tid"/>
        <!--这里的name对应Teacher类中的name, tname对应sql语句中的tname-->
        <result property="name" column="tname"/>
    </association>
</resultMap>

进行测试,运行结果如下:

Student(id=1, name=小明, teacher=Teacher(id=1, name=秦老师))
Student(id=2, name=小红, teacher=Teacher(id=1, name=秦老师))
Student(id=3, name=小张, teacher=Teacher(id=1, name=秦老师))
Student(id=4, name=小李, teacher=Teacher(id=1, name=秦老师))
Student(id=5, name=小王, teacher=Teacher(id=1, name=秦老师))

这中方式就类似于这样写 sql 语句:

select s.id sid,s.name sname,t.id tid,t.name tname from student s, teacher t where s.tid = t.id

sql 语句可以看出,这是一种联表查询的方式。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值