mybatis级联查询-collection
前期准备
准备数据
创建数据库jilian
在数据库中创建俩个表studen和teacher表,
俩者关系:teacher通过主键id和student表的teacher_id字段相关联(一对多关系)
建表语句
1 | CREATE TABLE teacher ( |
利用mybatis-generator生成相对应的实体类,dao和mapper
Student.java
1 | package com.java.ting.domain; |
StudentMapper.java
1 | import com.java.ting.domain.Student; |
StudentMapper.xml
1 | <resultMap id="BaseResultMap" type="com.java.ting.domain.Student"> |
Teacher.java
1 | import lombok.Getter; |
TeacherMapper.java
1 | public interface TeacherMapper { |
TeacherMapper.xml
1 |
|
新增一个TeacherDto用来接口级联查询出的数据
1 | import com.java.ting.domain.Student; |
在StudentMapper类中新建一个方法
1 | /** |
对应的mapper
1 | <select id="findStudentByTeacherId" resultMap="BaseResultMap"> |
在TeacherMapper类中新建俩个方法用来测试俩种方式
1 | List<TeacherDto> getTeacherAndStudentById(); |
对应的mapper
1 | <!-- 第一种 这个会多次查询关联表 n+1次--> |
新建个JiLianController用来测试
1 | import com.alibaba.fastjson.JSON; |
调用接口进行对比
启动项目后调用http://localhost:xxx/web/jilian/collection/select发现使用select的会和数据库进行4次交互,如下图(使用idea插件MyBatis Log Plugin)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
191 restore sql from selection - ==>
select id, `name`
FROM teacher;
------------------------------------------------------------------------------------------------------------------------
2 restore sql from selection - ==>
select id, student_name, teacher_id
FROM student
WHERE teacher_id = 1;
------------------------------------------------------------------------------------------------------------------------
3 restore sql from selection - ==>
select id, student_name, teacher_id
FROM student
WHERE teacher_id = 2;
------------------------------------------------------------------------------------------------------------------------
4 restore sql from selection - ==>
select id, student_name, teacher_id
FROM student
WHERE teacher_id = 3;
------------------------------------------------------------------------------------------------------------------------调用http://localhost:6850/web/jilian/leftJoin只会和数据库进行一次交互
1
2
3
4
5
6-- 5 2020-01-15 15:12:38.105 [http-nio-6850-exec-2] DEBUG c.j.t.m.T.getTeacherAndStudentByIdLeftJoin - ==>
select t.id, t.`name`, s.id as student_id, s.student_name as student_name, s.teacher_id as teacher_id
FROM teacher t
LEFT JOIN student s
ON t.id = s.teacher_id;
------------------------------------------------------------------------------------------------------------------------俩者五次调用的用时
次数 getTeacherAndStudentById方法 getTeacherAndStudentByIdLeftJoin方法 1 130ms 50ms 2 114ms 53ms 3 118ms 50ms 4 119ms 50ms 5 118ms 58ms
使用左连接的getTeacherAndStudentByIdLeftJoin的方法基本上都比使用拼接查询的getTeacherAndStudentById方法快上俩倍以上
详解俩种方法
- 第一种使用拼接查询的方法
1
2
3
4
5
6
7<resultMap id="BaseResultList" type="com.java.ting.dto.jilian.TeacherDto">
<id column="id" jdbcType="INTEGER" property="id"/>
<result column="name" jdbcType="VARCHAR" property="name"/>
<collection property="studentList" ofType="com.java.ting.domain.Student"
select="com.java.ting.mapper.StudentMapper.findStudentByTeacherId"
column="{teacherId = id}"/>
</resultMap>
property 中的参数要和TeacherDto实体类中的list属性名一样
ofType是该放回的实体类类型,
select的参数是关联的使用哪个查询方法;
column=”{teacherId = id} 中{}中的字段对应关系,teacherId 是Student实体对应的字段,id是上面result中相对应,column中的字段俩者在表中必须有关联关系。不然无法建立关系。
数据库的列名或者列标签别名。与传递给select中配置的方法名参数名称相同。注意: 在处理组合键时,可以使用column=“{prop1=col1,prop2=col2}”这样的语法,设置多个列名传入到嵌套查询语句。这就会把prop1和prop2设置到目标嵌套选择语句的参数对象中。
- 使用链接查询第二种和第一种的区别就是在collection中使用定制的resultMap和sql字段
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18<!-- 第二种 利用左链接查询 效率快-->
<resultMap id="BaseResultLeftJoin" type="com.java.ting.dto.jilian.TeacherDto">
<id column="id" jdbcType="INTEGER" property="id"/>
<result column="name" jdbcType="VARCHAR" property="name"/>
<collection property="studentList" resultMap="BaseStudent" />
</resultMap>
<resultMap id="BaseStudent" type="com.java.ting.domain.Student">
<id column="student_id" jdbcType="INTEGER" property="id"/>
<result column="student_name" jdbcType="VARCHAR" property="studentName"/>
<result column="teacher_id" jdbcType="INTEGER" property="teacherId"/>
</resultMap>
<sql id="Base_Column_List_left">
t.id, t.`name`, s.id as student_id, s.student_name as student_name, s.teacher_id as teacher_id
</sql>
<!-- 第二种 end-->
- collection中的property和第一种一样都是TeacherDto实体类对应的属性
- collection中的resultMap是使用地址的resultMap的id
- 定制的resultMap中的result的column一定要和上面的resultMap的字段不能重复否则无法正确的展示出先要的数据
- select标签中也要使用定制的 最好使用别名进行区分,此时要和定制的resultMap中的column中字段保持一致,因为如果不使用别名可能teacher表和student表中的字段名重复,导致数据展示异常
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 ting-个人博客!