很多开发人员之所以编写出低效的应用,有一大原因是并不理解怎样编写高效的SQL。以订单查询为例,我们经常需要查询某个用户的订单以及订单明细,并且以树形方式展现如下:

对于这种性质的功能,很多开发人员的做法是先查询主表,然后根据主表去循环子表,如下所示:

List<Department> depts = DepartmentMapper.queryDept();
for (Department dept: depts) {
dept.setEmps(EmployeeMapper.queryEmp(dept.id));
}

这种做法就是典型的过程性编程思维,它不仅在更改查询条件或字段时维护性差、不支持两个表的查询条件,而且性能低下,主表有几条记录就会导致请求数据库几次,不仅应用响应时间长,服务器也耗费了更多的资源。更好的做法是一次性查询会所有符合条件的记录,然后再应用中进行拆分并组装,主流的ORM框架几乎都支持这些模式,以使用最广泛的Mybatis为例,其结果映射resultMap中的association(用于一对一和多对一)和collection(用于一对多)元素支持自动将二位结果映射为主子对象。如下所示:

<mapper namespace="chapter6.dao.DepartmentMapper">
<!-- 嵌套结果集的方式,使用collection标签定义关联的集合类型的属性封装规则 -->
<resultMap type="chapter6.Department" id="MyDept">
<id column="did" property="id"/>
<result column="dept_name" property="departmentName"/>
<collection property="emps" ofType="chapter6.Employee">
<id column="eid" property="id"/>
<result column="last_name" property="lastName"/>
<result column="email" property="email"/>
<result column="gender" property="gender"/>
</collection>
</resultMap> <select id="queryDept" resultMap="MyDept" >
SELECT
d.id did,
d.dept_name dept_name,
e.id,
e.last_name last_name,
e.email email,
e.gender gender
FROM
tbl_dept d
LEFT JOIN tbl_employee e ON d.id = e.d_id
</select>
</mapper>

association同样可以实现相同功能,不过明细表是主表,如下所示:

<mapper namespace="com.abc.mapper.StudentMapper">
<select id="getById" parameterType="int"
resultMap="studentResultMap">
select s.id s_id,
s.name s_name,
s.gender s_gender,
s.major s_major,
s.grade s_grade,
t.id t_id,
t.name t_name,
t.gender t_gender,
t.title t_title,
t.research_area t_research_area
from student s left join teacher t
on s.supervisor_id = t.id
where s.id=#{id}
</select>
<resultMap id="studentResultMap" type="Student">
<id property="id" column="s_id" />
<result property="name" column="s_name" />
<result property="gender" column="s_gender" />
<result property="major" column="s_major" />
<result property="grade" column="s_grade" />
<!--使用resultMap属性引用下面的教师实体映射 -->
<association property="supervisor" javaType="Teacher"
resultMap="supervisorResultMap" />
</resultMap>
<!--教师实体映射 -->
<resultMap id="supervisorResultMap" type="Teacher">
<id property="id" column="t_id" />
<result property="name" column="t_name" />
<result property="gender" column="t_gender" />
<result property="researchArea" column="t_research_area" />
<result property="title" column="t_title" />
</resultMap>
</mapper>

需要注意的是,默认情况下Mapper中使用association标签,select 有大量相同的数据,此时会出现问题, 有的数据可以联查出来, 而有的不可以。此时需要开启缓存开关,参考https://blog.csdn.net/qq_27848369/article/details/80534253

mybatis 查询优化主子表查询之association和collection的更多相关文章

  1. MyBatis的多表查询笔记

    MyBatis的多表查询 随着学习的进步,需求的提高,我们在实际开发中用的最多的还是多表查询,就让我们一起学习MyBatis中的多表查询. 数据库准备 Class表 Student表 项目结构 这次使 ...

  2. 使用Mybatis进行连表查询、left join---https://blog.csdn.net/jinzhencs/article/details/51980518

    使用Mybatis进行连表查询.left join https://blog.csdn.net/jinzhencs/article/details/51980518

  3. SpringBoot集成Mybatis实现多表查询的两种方式(基于xml)

     下面将在用户和账户进行一对一查询的基础上进行介绍SpringBoot集成Mybatis实现多表查询的基于xml的两种方式.   首先我们先创建两个数据库表,分别是user用户表和account账户表 ...

  4. MyBatis实现关联表查询

    一.一对一关联 1.1.提出需求 根据班级id查询班级信息(带老师的信息) 1.2.创建表和数据 创建一张教师表和班级表,这里我们假设一个老师只负责教一个班,那么老师和班级之间的关系就是一种一对一的关 ...

  5. MyBatis——实现关联表查询

    原文:http://www.cnblogs.com/xdp-gacl/p/4264440.html 一.一对一关联 1.1.提出需求 根据班级id查询班级信息(带老师的信息) 1.2.创建表和数据 创 ...

  6. Mybatis系列(三):Mybatis实现关联表查询

    原文链接:http://www.cnblogs.com/xdp-gacl/p/4264440.html 一.一对一关联 1.1.提出需求 根据班级id查询班级信息(带老师的信息) 1.2.创建表和数据 ...

  7. MyBatis—实现关联表查询

    一.一对一关联 1.1.提出需求 根据班级id查询班级信息(带老师的信息) 1.2.创建表和数据 创建一张教师表和班级表,这里我们假设一个老师只负责教一个班,那么老师和班级之间的关系就是一种一对一的关 ...

  8. 07 Mybatis的多表查询1----1对多和多对1---@Results注解用法总结

    1.表与表之间的关系及其举例 表之间的关系有4种:一对多.多对一.一对一.多对多. 举例: (1)用户和订单就是一对多 一个用户可以下多个订单 (2)订单和用户就是多对一 多个订单属于同一个用户 (3 ...

  9. MyBatis框架——多表查询

    MyBatis多表查询, 从表中映射主表,使用 association 标签,通过设置 javaType 属性关联实体类: 主表映射从表,使用 collection 标签,通过 ofType 属性关联 ...

随机推荐

  1. Elasticsearch学习之图解Elasticsearch中的_source、_all、store和index属性

    转自 : https://blog.csdn.net/napoay/article/details/62233031 1. 概述 Elasticsearch中有几个关键属性容易混淆,很多人搞不清楚_s ...

  2. P5173 传球

    题目背景 临近中考,pG的班主任决定上一节体育课,放松一下. 题解:https://blog.csdn.net/kkkksc03/article/details/85008120 题目描述 老师带着p ...

  3. MySQL 在高并发下的 订单撮合 系统使用 共享锁 与 排他锁 保证数据一致性

    作者:林冠宏 / 指尖下的幽灵 掘金:https://juejin.im/user/587f0dfe128fe100570ce2d8 博客:http://www.cnblogs.com/linguan ...

  4. 算法提高 新建Microsoft Word文档

      算法提高 新建Microsoft Word文档   时间限制:1.0s   内存限制:256.0MB      问题描述 L正在出题,新建了一个word文档,想不好取什么名字,身旁一人惊问:“你出 ...

  5. React 学习之路 (一)

    先说一说对React的体验,总结 首先react相对angular来说入手简单暴力,在学习的这段时间里发现: 我们每天做的事就是在虚拟DOM上创建元素然后在渲染到真实的DOM中 渲染到真实DOM上的R ...

  6. Hibernate配置关系(申明:来源于csdn)

    hibernate中多对一.一对一.一对多.多对多的配置方法 地址:http://blog.csdn.net/communicate_/article/details/8445437

  7. SVN操作步骤

    1.第一次检出 svn co svn://192.168.1.1:5555/MMM 2.代码更新 svn update 3.代码提交 svn add *.c svn commit -m "d ...

  8. 请大神留言:使用static方法和从Spring IOC 容器里面取出的方法有什么区别????

    类的静态方法,不用new出对象,因为它在类的初始化阶段加载到jvm内存的. 而spring容器,是在启动服务的时候,new出容器所管理的对象. 本质区别就是一个在堆中产生了对象,一个没产生对象只在方法 ...

  9. 将 ASP.NET Core 2.0 项目升级至 ASP.NET Core 2.1 RC 1

    今天微软发布了 .NET Core 2.1 RC 1 ,虽然只是 Release Candidate 版,但已经可以在生产环境中使用. NET Core 2.1 RC is supported by ...

  10. Linux:使用rpcgen实现64位程序调用32位库函数

    摘要:本文介绍使用rpcgent实现64位程序调用32位库函数的方法,并给出样例代码. 我的问题 我的程序运行在64位Linux系统上,需要使用一个从外部获得的共享库中的函数,这个共享库是32位的,无 ...