Mybatis学习 association关联 和 collection集合

MySQL中的多对一、一对多关系

· 多对一

如老师和学生,很多个学生由一个老师教,这个时候就是多对一关系。
可以定义学生和老师实体类如下:

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

数据库存储如下图
teacher表

idname
1X导
2吸导

student表

idnametid
1Salier1
2云烟客1
3Kaola2

如何得到所有的学生和它们对应的老师呢
以下代码可以得到所有的学生的信息

   <select id="getStudent" resultType = "Student">
            select * from mybatis.student;
   </select>

得到的结果中 teacher对应的是null

那么如何将数据库中student表中的tid和student实体类中的teacher对应起来呢

答案是使用resultMap映射集
我们知道,通过映射集可以将实体类中的元素与数据库中的字段对应起来,完成不同命名的元素之间的数值的映射,但是,将数据库中的 int 类型的 id 映射到实体类 Teacher 上的话,就不能用resultMap中的 result 标签了,在这里,需要用 association 标签。
association 标签通过映射的方式将从 student 表中获得的 tid 以 teacher 对象的形式展示。

得到结果有两种方式,一种是使用子查询的方式,另一种是嵌套查询

首先是子查询
   <select id="getStudent" resultType = "StudentTeacher">
            select * from mybatis.student;
   </select>

	<resultMap id="StudentTeacher" type="Student">
            <result property="id" column="id"/>
            <result property="name" column="name"/>
            <association property="teacher" column="tid" javaType="Teacher" select="getTeacher"/>
        </resultMap>

其中的 association 标签 ,property 为在student实体类中的内容,column 代表着 student 实体类中 teacher对象 将要对应的数据库中的字段,javaType 为要转换的实体类的类型,select 为被嵌套的子方法,该方法如下

        <select id="getTeacher" resultType="Teacher">
            select * from mybatis.teacher where id = #{tid};
        </select>

测试以上配置文件能否得到所有学生以及对应的老师

    @Test
    public void getStudent(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();

       StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);

       List<Student> students = mapper.getStudent();

        for (Student student : students) {
            System.out.println(student);
        }


        sqlSession.close();
    }

得到运行结果
运行结果

然后是嵌套查询

代码如下

<select id="getStudent2" resultMap="StudentTeacher2">
	select s.id sid,s.name sname,t.name tname from mybatis.teacher t,mybatis.student s where s.tid = t.id;
</select>

<resultMap id="StudentTeacher2" type="Student">
    <result property="id" column="sid"/>
    <result property="name" column="sname"/>
    <association property="teacher" javaType="Teacher">
        <result property="name" column="tname"/>
    </association>
</resultMap>

与子查询不同的是,嵌套查询将问题的解决方案完全交给了SQL语句,在 association 标签中,没有再执行第二次查询,而是将 teacher 表中的 name 字段,映射到了SQL语句中的 tname 字段上,从而得到每个学生对应的教师名称。测试后得到的结果如下:
运行结果
可以得到预期的结果。

· 一对多

像一个老师教很多个学生的情况,就是一对多的关系。
可以定义老师和学生的实体类如下

@Data
public class Student {
    private int id;
    private String name;
    private int tid;
}
@Data
public class Teacher {
    private int id;
    private String name;
    private List<Student> students;
}

在多对一关系中,我们将 student 表中的 tid 字段通过 association 字段映射到了 Student 实体类中的teacher对象上,那么,在一对多关系中,Teacher 实体类中的 Student 泛型的集合应该如何映射?

答案是使用collection标签

collection 可以将数据库中的多个相同字段,映射到一个集合中。

嵌套查询

代码如下:

<select id="getTeacher2" resultMap="StudentTeacher">
    select s.id sid,s.name sname,t.name tname,t.id tid
    from mybatis.student s,mybatis.teacher t
    where s.tid = t.id and t.id = #{tid};
</select>

<resultMap id="StudentTeacher" type="Teacher">
    <result property="id" column="tid"/>
    <result property="name" column="tname"/>
    <collection property="students" ofType="Student">
        <result property="id" column="sid"/>
        <result property="name" column="sname"/>
        <result property="tid" column="tid"/>
    </collection>
</resultMap>

ofType是 collection 标签所映射的集合的泛型的类型

测试代码:

@Test
    public void getTeacher2(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();

        TeacherMapper mapper = sqlSession.getMapper(TeacherMapper.class);
        Teacher teacher =  mapper.getTeacher2(1);
        System.out.println(teacher);

        sqlSession.close();
    }

代码的测试结果如下:
在这里插入图片描述

子查询

代码如下:

<select id="getTeacher" resultMap="StudentTeacher2">
       select * from mybatis.teacher where id = #{tid};
   </select>

<resultMap id="StudentTeacher2" type="Teacher">
    <collection property="students" javaType="ArrayList" select="getStudentByTeachedID" column="id"/>
</resultMap>

<select id="getStudentByTeachedID" resultType="Student">
    select * from mybatis.student where tid = #{tid};
</select>

该部分比较难理解

collection 标签中, property 代表着实体类中的元素名,而数据库中并没有对应的字段,所以 column 字段我们先不写,javaType 是指的 property 所映射的元素的数据类型,为 ArrayList 型。子查询的代码为getStudentByTeachedID 方法,所以 select中为getStudentByTeachedID,最后 getStudentByTeachedID方法可以查询到的 teacher 的 id ,name 所以 我们从中选一个作为前面 property 所对应的 column,即column = " id "。

测试代码:

@Test
    public void getTeacher(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();

        TeacherMapper mapper = sqlSession.getMapper(TeacherMapper.class);
        Teacher teacher1 = mapper.getTeacher(2);
        System.out.println(teacher1);

        sqlSession.close();
    }

代码运行结果:
在这里插入图片描述

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值