MyBatis框架使用笔记-3(多表查询)

1.概述

在此前的应用中,我们设计一个实体类对应一个数据库的表。在查找记录的时候,我们在mapper.xml的select标签中使用resultType属性来指定需要进行返回的实体类对象,myBatis会自动完成表字段与实体类成员变量之间的映射关系。

  • 如下一个Teacher表对应一个Teacher实体类
    teacher表
public class Teacher {

    private int id;     	//老师编号
    private String name;   	//老师姓名

    public Teacher() {
    }

    public Teacher(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Teacher{" +
                "id2=" + id2 +
                ", name2='" + name2 + '\'' +
                '}';
    }
}
  • 通过指定resultType,myBatis进行自动映射(要求数据表字段名与实体类成员变量名一一对应)。如id字段的值则通过setId()方法赋给id成员变量。
    <select id="selectById" parameterType="int" resultType="Teacher">
        select *
        from teacher
        where id = #{param1};
    </select>

2.实现多表查询的方式

但当需要进行多表查询的时候,即查询的结果包含了多个表的内容,使用上述的一个实体类对应一个数据表的方式难以获取所有的结果。如下,我们需要在查找Teacher信息的同时把Teacher的Student信息也一并查出。或则在查找Student的同时把Student的Teacher信息也一起查出。
老师表 学生表

 	private int id;                        //老师编号
    private String name;                   //老师姓名
    private List<Student> studentList;      //学生列表
    private int id;             //学生编号
    private String name;        //学生姓名
    private int age;            //学生年龄
    private int tid;            //老师编号
    private Teacher teacher;    //老师信息

为了实现多表查询有以下三种方式:

2.1.使用业务装配

在service层组装两次查询的结果,如下查出student记录后,再遍历结果在遍历的过程中查出相应的teacher记录。

SqlSession session = MyBatisUtil.getSession();
        StudentMapper sm = session.getMapper(StudentMapper.class);
        List<Student> list = sm.selectByInfo(pi);
        TeacherMapper tm = session.getMapper(TeacherMapper.class);
        for (Student s : list) {
            Teacher t = tm.selectById(s.getTid());
            s.setTeacher(t);
        }

2.2. 使用Auto Mapping

对多个表进行连接查询,然后用别名进行映射。如t.id起别名为teacher.id,则myBatis自动寻找student实体类中的teacher变量并调用其setId()方法进行赋值。

    <select id="selectAll" resultType="com.bear.sxt.pojo.Student">
        select
            t.id   `teacher.id`,
            t.name `teacher.name`,
            s.id   id,
            s.name name,
            s.age  age,
            s.tid  tid
        from student s left join teacher t on t.id = s.tid;
    </select>

2.3.使用resultMap标签

利用resultMap标签可以构建任意的映射关系。

2.3.1.相关标签

  • id标签:主键映射
  • result标签:非主键字段映射
  • association标签:单个对象映射
  • collection标签:多个对象映射

2.3.2. 相关属性

  • column:数据库表中字段名
  • property:实体类中成员变量的名称

通过column和property,即使字段名与变量名不一样也可以完成映射

2.3.3.使用select属性进行额外查询

将原本在业务层中进行装配的查询逻辑移到Mapper.xml中进行。

  • N+1查询:查找学生记录(包含了一个teacher,用association)
    <resultMap id="studentMap" type="com.bear.sxt.pojo.Student">
        <!--这些一一对应的字段可以省略,mybatis会采用auto mapping的方式自行对应-->
		<id column="id" property="id"/>
        <result column="name" property="name"/>
        <result column="age" property="age"/>
        <!--由于tid需要作为参数进行额外的查询,如果这里不写myBatis只会进行一次result.tid到association.tid的映射
        这样会导致association中的查询不准确,所以这里一定不能省略-->
        <result column="tid" property="tid"/>
        <!--association标签的作用是进行额外的查询,select为所执行的查询标签,column为需要作为参数传入的字段-->
        <association property="teacher" select="com.bear.sxt.mapper.TeacherMapper.selectById" column="tid"/>
    </resultMap>

    <select id="selectAll" resultMap="studentMap">
        select *
        from student
    </select>
  • 集合查询:查找老师记录(包含了多个student,使用collection)
    <resultMap id="teacherMap" type="com.bear.sxt.pojo.Teacher">
        <!--主键使用id配置映射-->
        <id column="id" property="id"/>
        <!--其他字段使用result配置映射-->
        <result column="name" property="name"/>
        <!--collection标签的作用是进行额外的查询(和association类似,一个返回列表,一个返回单个对象),select为所执行的查询标签,column为需要作为参数传入的字段-->
        <collection property="studentList" select="com.bear.sxt.mapper.StudentMapper.selectByTid" column="id"/>
    </resultMap>

    <select id="selectAll" resultMap="teacherMap">
        select *
        from teacher;
    </select>

2.3.4 连接查询

  • 2.3.3中可以使用连接查询查找老师的记录,这样就不需要额外的查询语句了。
  • 如果使用的是collection标签则使用ofType标签指明容器元素类型,如果使用的是association标签则使用javaType标签表明对象的类型。
    <resultMap id="teacherMap2" type="com.bear.sxt.pojo.Teacher">
        <!--当存在collection时mybatis会自动将重复的tid合并为一条记录-->
        <!--当不存在collection时,mybatis不会合并重复tid的记录-->
        <id column="tid" property="id2"/>
        <result column="tname" property="name2"/>
        <!--由于连接查询可以查到student表中的内容,所以这里可以直接进行映射,而不像selectById中使用额外查询-->
        <collection property="studentList" ofType="com.bear.sxt.pojo.Student">
            <id column="sid" property="id"/>
            <result column="sname" property="name"/>
            <result column="sage" property="age"/>
            <result column="tid" property="tid"/>
        </collection>
    </resultMap>
    <select id="selectAll" resultMap="teacherMap2">
        select
            t.id   tid,
            t.name tname,
            s.id   sid,
            s.name sname,
            s.age  sage
        from teacher t left join student s on t.id = s.tid;
    </select>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值