目录

  1. 概述
  2. 业务层进行联合
  3. DAO 层进行联合
    1. 分步骤联合查询
    2. 统一联合查询
    3. 查询关联集合对象
  4. 附录

在项目中经常遇到多表联合查询的情况,通过逆向生成的 Mapper 并不能够完成这项任务,所以多表联合需要手动编写,那么如何操作才能够写出优雅的联合查询尼?

概述

有这样一个例子:一个学生可以有多个老师,一个老师也可以传授知识给多个学生

这里主要给出两个解决办法:

  • 业务装配对两个表写单独的 sql 语句,在业务(service)把查询结果进行联合
  • 使用 Mybatis 的<resultMap>标签进行实现

业务层进行联合

使用业务层进行联合处理,可以在需求更改的条件下,减少修改面的蔓延程度,但是在实际项目中,这么做可能影响服务性能,毕竟是在 Service 手动进行操作,当然没有数据库自身操作快捷

DAO 层进行联合

这种方式可以使用<resultMap>标签将两个表中的对象关联起来

分步骤联合查询

首先进行简单的N:1联合查询,随后给出M:N联合查询的解决方式

学生实体类
1
2
3
4
5
6
7
public class Student {
private int id;
private String name;
private int age;
private int tid;
private Teacher teacher;//包含在另一张表
}
TeacherMapper.xml
1
2
3
4
5
<mapper namespace="com.test.mapper.TeacherMapper">
<select id="selById" parameterType="int" resultType="Teacher">
select _ from teacher where id =#{0}
</select>
</mapper>
StudentMapper.xml
1
2
3
4
5
6
7
8
9
10
11
12
<mapper namespace="com.test.mapper.StudentMapper">
<resultMap type="Student" id="stuMap">
<id column="id" property="id"/>
<result column="name" property="name"/>
<result column="age" property="age"/>
<result column="tid" property="tid"/>
<association property="teacher" select="com.test.mapper.TeacherMapper.selById" column="tid"/>
</resultMap>
<select id="selAll" resultMap="stuMap" >
select _ from student
</select>
</mapper>

装配对象时使用,其中 property 表示类中的属性名 select 表示要执行的 sql 语句,column 表示要传过去的字段参数

这种方式实现的细节就是:先一条 sql 查询出所有的学生,然后再查每个学生的学生,这是一种分布骤的方式,没有下面这种一次性的查找快捷

统一联合查询

StudentMapper.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

<!-- 在mapper中实现联合查询 -->
<resultMap type="Student" id="stuMap1">
<id column="sid" property="id"/>
<result column="sname" property="name"/>
<result column="sage" property="age"/>
<result column="tid" property="tid"/>
<association property="teacher" javaType="teacher">
<id column="tid" property="id"/>
<result column="tname" property="name"/>
</association>
</resultMap>
<select id="selAll1" resultMap="stuMap1">
select s.id sid,s.name sname,s.age sage,t.id tid,t.name tname
from student s left join teacher t on s.tid = t.id;
</select>

查询关联集合对象

上面是N:1解决方案,现在给出M:N解决方案

教师实体类
1
2
3
4
5
public class Student {
private int id;
private String name;
private List<Student> teacher;//包含在另一张表
}

同样可以分步骤查询或者以统一查询,这里就直接给出统一查询的配置文件了

fileName
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

<!-- 使用联合查询 -->
<resultMap type="Teacher" id="teacMap1">
<id column="tid" property="id"/>
<result column="tname" property="name"/>
<collection property="list" ofType="Student">
<id column="sid" property="id"/>
<result column="sname" property="name"/>
<result column="age" property="age"/>
<result column="tid1" property="tid"/>
</collection>
</resultMap>
<select id="selAll1" resultMap="teacMap1">
select t.id tid, t.name tname, s.id sid, s.name sname,age ,s.tid tid1
from teacher t left join student s on t.id = s.tid
</select>

附录

MyBatis 多表联合查询及优化
Mybatis 实现多表联查