MyBatis学习笔记-11-复杂查询-resultMap


复杂查询CRUD.

目录结构

多对一(假设多个学生被一个老师教).

一个Student实体里面有一个Teacher类型属性,学生与老师对应关系是多对一

测试环境搭建.

(已配置好mybatis-config.xml配置文件,写好MybatisUtils.java工具类)

1.导入lombok.
2.新建数据库 写入数据.
CREATE TABLE `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, '老师1');

CREATE TABLE `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','1'),
('2','学生2','1'),
('3','学生3','1'),
('4','学生4','1'),
('5','学生5','1');
3.新建实体类(重点).
@Data
public class Student {
    private int id;
    private String name;
    private Teacher teacher; // 一个学生实例 里面有 一个老师
}
@Data
public class Teacher {
    int id;
    String name;
}
4.新建Mapper接口.
public interface StudentMapper {

}
public interface TeacherMapper {

}
5.建立Mapper.xml文件.
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="dao.TeacherMapper">
</mapper>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="dao.StudentMapper">
</mapper>
6.绑定Mapper到mybatis-config.xml.
<mappers>
    <mapper resource="dao/StudentMapper.xml"/>
    <mapper resource="dao/TeacherMapper.xml"/>
</mappers>

按照查询嵌套处理.

  • 创建两个查询语句,一个查询套着另一个查询(通过一个表的外键,查出对应另一个表的内容,然后将这些内容,与前表关联合并)

接口方法

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

StudentMapper.xml SQL语句编写

<!--
    这种方式相当于 子查询

    select id,name,tid from mybatis.student  ==> tid

-->
<mapper namespace="dao.StudentMapper">
    <select id="getStudent" resultMap="StudentTeacher">
        select * from mybatis.student;
    </select>
    <resultMap id="StudentTeacher" type="pojo.Student">
        <result property="id" column="id"/>
        <result property="name" column="name"/>
        <association property="teacher" column="tid" javaType="pojo.Teacher" select="getTeacher"/>
    </resultMap>
    <select id="getTeacher" resultType="pojo.Teacher">
        select * from mybatis.teacher where id=#{tid};
    </select>
</mapper>

上面的 association 中的 column : tid 是指①在getStudent中 结果列中 某一个值对应的别名或名字 (tid)②同样也是即将传入getTheacher的 #{对应名字的参数}

无论sql是否在同一个mapper.xml文件中,都可以使用 association 的select属性(需要全限定名)去加载sql,获取其返回结果(多对一:单个结果–对象,一对多:多个结果-List<对象>)

测试

@Test
public void getStudent(){
    try(SqlSession sqlSession = MybatisUtils.getSqlSession();) {
        StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
        List<Student> list = studentMapper.getStudent();

        list.forEach(System.out::println);
    }
}

结果展示

按照结果嵌套处理.

  • 一条查询语句,需要在resultMap中进行处理,对sql编写能力要求高

与查询嵌套处理一致,除了StudentMapper.xml文件内容不一样

StudentMapper.xml编写Sql

<mapper namespace="dao.StudentMapper">
    <select id="getStudent" resultMap="StudentTeacher">
        select s.id sid,s.name sname,t.id tid, t.name tname
        from student s, teacher t
        where s.tid = t.id;
    </select>
    <resultMap id="StudentTeacher" type="pojo.Student">
        <result property="id" column="sid"/>
        <result property="name" column="sname"/>
        <association property="teacher" javaType="pojo.Teacher">
            <result property="id" column="tid"/>
            <result property="name" column="tname"/>
        </association>
    </resultMap>
</mapper>

结果展示

一对多(假设一个老师教多个学生).

  • 教师表的一条记录对应学生表的多条记录

一个Teacher实体中有一个 List<Student>类型的属性

对于多对多的情况,就需要一个中间实体(包含两个实体的主键)

一个Teacher实体中有一个List<Student>类型的属性

一个Student实体中有一个List<Teacher>类型的属性

一个Teacher_Student实体 包含 Teacher和Student两个实体的主键 作为外键 当然可以把这个两个属性作为联合主键

//实体类
class Teacher{
    int id;
    int name;
}
class Student{
    int id;
    int name;
}
class Studnet{
    int tid;
    int sid;
    /*
        tid,sid 联合为主键 (tid 不是主键,sid不是主键,两个合起来才叫主键)
        tid : 作为外键(Teacher)
(Student)
    */
}

多对多.

就是两个一对多

小结.

两种查询方式比较.

  • 嵌套查询的查询语句写起来简单,但是执行的sql语句多,性能要低一点
  • 嵌套结果的查询语句写起来难一点,而且sql语句只执行一条,性能相对较高

复杂的属性,我们需要单独处理 – 即除了基本类型.

  • 对象:association – 多对一
  • 集合:collection – 一对多

javaType 和 ofType.

javaType:指定实体类中属性的类型 但是如果是类型是集合 就使用ofType
ofType:用于指定集合中的泛型的约束类型

一对一.

比如qq账号 和 qq空间

一个账号对应一个空间,一个空间对应一个账号

外键可以在任意一个表上

一对多和多对一.

假设 所有学生只有一个老师教 用班级和学生好

  • 多个学生被一个老师教,且每个学生只有一个老师
  • 一个老师教多个学生 (一个老师有多个学生)
  • 学生依赖于老师,学生表为子表(存在主键和外键),老师表为父表(只有主键)

多对多.

假设 所有学生有多个老师教 其实老师和学生符合多对多

  • 一个学生被多个老师教(每个学生有多个老师)
  • 一个老师教多个学生(每个老师有多个学生)
  • 此时比较复杂,必须要一个中间表

这位老哥写的很好:https://www.cnblogs.com/jimisun/p/9414148.html


文章作者: liuminkai
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 liuminkai !
评论
 上一篇
对象关系(重点) 对象关系(重点)
对象关系. 泛化 实现 依赖 关联: 单向 一对一 单向 多对一 单向 一对多 单向 多对多 聚合 组合 一、泛化关系(generalization). 就是继承关系 (类和类之间–单继承,接口和接口之间–多继承) 关键字 : ext
2020-07-25
下一篇 
MyBatis学习笔记-10-Mybatis执行流程 MyBatis学习笔记-10-Mybatis执行流程
Mybatis执行流程 sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);分析. 1.第一步,实例化SqlSessionFactoryBuilder调用方法build
2020-07-24
  目录