声明:面试是遇到延迟加载问题,在网页搜索到此篇文章,感觉很有帮助,留此学习之用!

一、分步查询

分步查询通常应用于关联表查询,如:电商平台,查询订单信息时需要查询部分的用户信息;OA系统查询个人信息时需要查询部门信息,反之亦是。相对于关联查询来说,分步查询将查询sql拆分,这里引申出一个问题是:分步查询与关联表查询的不同。

从代码层面来说:关联表查询能够有效的简化代码编写逻辑,减小代码编写难度,同时避免B-U-G(代码多了,bug   就多了);

而分步查询则能够增强代码的可用性(这点我也不是非常理解,在实际开发中也未遇到过)

从功能上说:关联表查询毕竟只需要查询一次数据库,对于业务量较小的系统来说,效率更高,数据库压   力相对较小;

分步查询虽然需要多次查询数据,但是这也意味着能够更好地使用数据缓存服务,且缓存的   数据耦合度低,利用率高,而且单次查询效率很高,数据库压力较小(对于业务量较大的系    统来说)。还有一点则是数据库锁的问题,毕竟关联查询是多表同时使用,分步查询每次只    操作一个表。

分步查询的实现(以简单的OA系统为例)

业务场景一:嵌套标签association的应用---查询员工信息时,获取员工所在的部门信息。

1.建立员工与部门实体类

/*** 员工实体类* * @author xuyong**/
public class Employee {private Integer id;private String lastName;private String gender;private String email;private Department department;private Integer dId;public Integer getdId() {return dId;}public void setdId(Integer dId) {this.dId = dId;}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getLastName() {return lastName;}public void setLastName(String lastName) {this.lastName = lastName;}public String getGender() {return gender;}public void setGender(String gender) {this.gender = gender;}public String getEmail() {return email;}public void setEmail(String email) {this.email = email;}public Department getDepartment() {return department;}public void setDepartment(Department department) {this.department = department;}@Overridepublic String toString() {return "Employee [dId=" + dId + ", department=" + department+ ", email=" + email + ", gender=" + gender + ", id=" + id+ ", lastName=" + lastName + "]";}
}

  

/*** 部门实体类* * @author xuyong**/
public class Department {private Integer id;private String departmentName;private List<Employee> employee;public List<Employee> getEmployee() {return employee;}public void setEmployee(List<Employee> employee) {this.employee = employee;}/*** */private Department() {super();// TODO Auto-generated constructor stub}/*** @param id* @param departmentName*/private Department(Integer id, String departmentName) {super();this.id = id;this.departmentName = departmentName;}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getDepartmentName() {return departmentName;}public void setDepartmentName(String departmentName) {this.departmentName = departmentName;}@Overridepublic String toString() {return "Department [departmentName=" + departmentName + ", employee="+ employee + ", id=" + id + "]";}}

2.JUNIT单元测试编写

  获取sqlSession实例(未使用框架,自己手动获取)

/*** 获取sqlSession实例* @return* @throws IOException*/public SqlSessionFactory getSessionFactory() throws IOException {String resource = "mybatis-config.xml";InputStream inputStream = Resources.getResourceAsStream(resource);return new SqlSessionFactoryBuilder().build(inputStream);}

  业务方法

/*** 分布查询实现:*    获取员工信息及部门信息* @throws IOException*/@Testpublic void test08() throws IOException {SqlSessionFactory sessionFactory = getSessionFactory();SqlSession sqlSession = sessionFactory.openSession();try {EmployeeDaoPlus dao = sqlSession.getMapper(EmployeeDaoPlus.class);Employee employee = dao.getEmpByIdStep(1);System.out.println(employee);} catch (Exception e) {e.printStackTrace();} finally {sqlSession.close();}}

 在Mapper中定义接口

/*** 员工类Mapper接口* * @author xuyong**/
public interface EmployeeDaoPlus {/*** 分步查询测试*  获取员工信息同时获取部门信息* @param id* @return*/Employee getEmpByIdStep(Integer id);}

 编写对应的XML(sql资源文件)文件

<!-- 使用association分布查询 --><select id="getEmpByIdStep" resultMap="MyEmpByStep">select * from employee where id=#{id}</select>

 以下为查询结果,可以看到打印了两次sql

[com.xuyong.dao.EmployeeDaoPlus.getEmpByIdStep]-==>  Preparing: select * from employee where id=? [com.xuyong.dao.EmployeeDaoPlus.getEmpByIdStep]-==> Parameters: 1(Integer)[com.xuyong.dao.EmployeeDaoPlus.getEmpByIdStep]-<==    Columns: id, last_name, gender, email, d_id[com.xuyong.dao.EmployeeDaoPlus.getEmpByIdStep]-<==        Row: 1, 徐永, 男, t1heluosh1@163.com, 1[com.xuyong.dao.DepartmentDao.getDepartmentById]-====>  Preparing: select id,department_name from department where id=? [com.xuyong.dao.DepartmentDao.getDepartmentById]-====> Parameters: 1(Integer)[com.xuyong.dao.DepartmentDao.getDepartmentById]-<====    Columns: id, department_name[com.xuyong.dao.DepartmentDao.getDepartmentById]-<====        Row: 1, 文案部[com.xuyong.dao.DepartmentDao.getDepartmentById]-<====      Total: 1[com.xuyong.dao.EmployeeDaoPlus.getEmpByIdStep]-<==      Total: 1Employee [dId=1, department=Department [departmentName=文案部, employee=null, id=1], email=t1heluosh1@163.com, gender=男, id=1, lastName=徐永]

业务场景二:嵌套标签collection的应用---查询部门信息时,获取该部门下所有的员工。
  collection主要用于映射集合数据,工作中常见的应用场景有:

  订单查询、地址查询、产品分类查询

  Junit单元测试

/*** 分步查询*    查询部门时获取部门里所有的员工信息* * @throws IOException*/@Testpublic void test10() throws IOException {SqlSessionFactory sessionFactory = getSessionFactory();SqlSession sqlSession = sessionFactory.openSession();try {DepartmentDao dao = sqlSession.getMapper(DepartmentDao.class);Department department = dao.getDeptAndAEmpsByStep(1);/*EmployeeDaoPlus dao2 = sqlSession.getMapper(EmployeeDaoPlus.class);Employee employee = dao2.getEmpById(department.getEmployee().get(0).getId());*/System.out.println(department);} catch (Exception e) {e.printStackTrace();} finally {sqlSession.close();}}

接口定义此处忽略

XML文件编写

<!-- collection分布查询 --><resultMap type="com.xuyong.entity.Department" id="DepartAndEmpByStep"><id column="id" property="id"/><result column="department_name" property="departmentName"/><collection property="employee" select="com.xuyong.dao.EmployeeDaoPlus.getEmpByDid" column="id"></collection></resultMap><!-- collection分布查询部门下的所有员工信息 --><select id="getDeptAndAEmpsByStep" resultMap="DepartAndEmpByStep">select id,department_name from departmentwhere id = #{id}</select>

  查询结果

[com.xuyong.dao.DepartmentDao.getDeptAndAEmpsByStep]-==>  Preparing: select id,department_name from department where id = ? [com.xuyong.dao.DepartmentDao.getDeptAndAEmpsByStep]-==> Parameters: 1(Integer)[com.xuyong.dao.DepartmentDao.getDeptAndAEmpsByStep]-<==    Columns: id, department_name[com.xuyong.dao.DepartmentDao.getDeptAndAEmpsByStep]-<==        Row: 1, 文案部[com.xuyong.dao.EmployeeDaoPlus.getEmpByDid]-====>  Preparing: select * from employee where d_id = ? [com.xuyong.dao.EmployeeDaoPlus.getEmpByDid]-====> Parameters: 1(Integer)[com.xuyong.dao.EmployeeDaoPlus.getEmpByDid]-<====    Columns: id, last_name, gender, email, d_id[com.xuyong.dao.EmployeeDaoPlus.getEmpByDid]-<====        Row: 1, 徐永, 男, t1heluosh1@163.com, 1[com.xuyong.dao.EmployeeDaoPlus.getEmpByDid]-<====        Row: 4, 张三, 女, 123131313, 1[com.xuyong.dao.EmployeeDaoPlus.getEmpByDid]-<====      Total: 2[com.xuyong.dao.DepartmentDao.getDeptAndAEmpsByStep]-<==      Total: 1Department [departmentName=文案部, employee=[Employee [dId=1, department=null, email=t1heluosh1@163.com, gender=男, id=1, lastName=徐永], Employee [dId=1, department=null, email=123131313, gender=女, id=4, lastName=张三]], id=1]

  

二、延迟加载

  什么是延迟加载?

  当我们在某项业务里需要同时获取A、B两份数据,但是B这份数据又不需要立即使用(或者存在压根就不会使用的情况),当程序需要加载B时,再去请求数据库来获取B数据,而不是一次性将数据全部取出来或者重新发送一份请求,这就是延迟加载。

MyBatis默认关闭延迟加载技术,需要我们在配置文件里手动配置,配置如下:

<!-- 设置 --><settings><!-- 驼峰命名映射 --><setting name="mapUnderscoreToCamelCase" value="true"/><setting name="jdbcTypeForNull" value="NULL"/><!-- 懒加载设置 --><setting name="lazyLoadingEnabled" value="true"/>  <!-- 侵入懒加载,设置为false则按需加载,否则会全部加载 --><setting name="aggressiveLazyLoading" value="false"/><!-- 标准日志输出 --><!--<setting name="logImpl" value="STDOUT_LOGGING"/>--><!-- log4j日志输出 --><setting name="logImpl" value="LOG4J"/></settings>

  

注意:
  1. lazyLoadingEnabled与aggressiveLazyLoading必须全部设置,且lazyLoadingEnabled为true,aggressiveLazyLoading为false才能让延迟加载真正生效

  2.  toString与重载方法过滤:

通常我们在测试时会在实体类加入toString,或者存在了一些重载方法,这些MyBatis会对其进行过滤,但是过滤会调     用cglib与asm指定包,因此要将两个包添加到buildpath。以下为两个包的maven依赖:

         <dependency><groupId>cglib</groupId><artifactId>cglib</artifactId><version>3.1</version></dependency><dependency><groupId>asm</groupId><artifactId>asm</artifactId><version>3.3.1</version></dependency>

  

3.如果想单个开启或禁用延迟加载,可以使用fetchType属性来实现

<!-- collection分布查询 -->
        <resultMap type="com.xuyong.entity.Department" id="DepartAndEmpByStep">
        <id column="id" property="id"/>
        <result column="department_name" property="departmentName"/>
        <!-- 多个值传递可封装成map如:column="{key1=column1,...}"
             fetchType="lazy" 表示使用懒加载   fetchType="eager"表示禁用懒加载
        -->
        <collection property="employee" select="com.xuyong.dao.EmployeeDaoPlus.getEmpByDid" column="{id=id}" fetchType="lazy"></collection>
        </resultMap>

转载于:https://www.cnblogs.com/wang-Java-begining/p/9884927.html

MyBatis学习——分步查询与延迟加载相关推荐

  1. association 实现MyBatis分步查询与延迟加载

    一.分步查询 1.1什么时候可以用到分步查询 有的时候需要我们对数据库进行关联查询,比如Employee 持有另一个Department对象的一个引用,我们希望在查询Employee 的时候把Depa ...

  2. mybatis分步查询与延迟加载

    参考地址:https://blog.csdn.net/postersxu/article/details/79053916 本篇博客的主题是如何实现MyBatis的延迟加载(也叫懒加载),因为延迟加载 ...

  3. JavaEE——Mybatis(6)--association的分步查询与延迟加载 以及Collection和鉴别器discriminator...

    使用association进行分步查询:(一般,部门什么的会有自己的Mappper,所以直接利用就好,不用再重新自己写) 1.先按照学生id查询学生信息 2.根据查询学生信息中的grade_id值去班 ...

  4. 【Java从0到架构师】MyBatis - 多表查询_延迟加载

    多表查询_延迟加载 多表关系 一对一 association 标签 + JOIN 实现一对一 一对多 \ 多对一 collection 标签 + LEFT JOIN 实现一对多 多对多 多对多的本质: ...

  5. Mybatis的一对一查询以及延迟加载

    一对一的关联查询: 使用业务扩展类 使用ResultMap 表如下 create table student(sid int(11) primary key not null, sname varch ...

  6. mybatis学习(22):查询排序

    按照某列排序 目录结构 com.geyao.mybatis.mapper BlogMapper类 package com.geyao.mybatis.mapper;import java.util.L ...

  7. mybatis 学习的总结

    什么是mybatis? 他是java基于持久层的框架(和数据库交互的一层),它支持定制化 SQL.存储过程以及高级映射(不像hibernate把发送sql作为暗箱操作,而他是可以完全看出来的可以看的到 ...

  8. [mybatis]映射文件_select_resultMap_关联查询_association分步查询延迟加载

    association分步查询 场景一 查询Employee的同时查询员工对应的部门 Employee===Department 一个员工有与之对应的部门信息 Employee表: Departmen ...

  9. mybatis学习笔记(13)-延迟加载

    2019独角兽企业重金招聘Python工程师标准>>> mybatis学习笔记(13)-延迟加载 标签: mybatis [TOC] resultMap可以实现高级映射(使用asso ...

最新文章

  1. 深证信息等三方拟联合开展大数据研究
  2. ModuleNotFoundError: No module named 'rospkg'
  3. 【赠书】重磅好书联邦学习实战来袭!你值得拥有一本
  4. Kafka 输入行太长 命令语法不正确
  5. mysql如何修改所有的definer
  6. z490 linux raid,华硕z490主板装win7系统及bios设置教程(支持10代usb驱动)
  7. 程序员职业自由6个阶段,你处于哪个?
  8. 对编码通俗易懂的介绍
  9. Android高级开发-布局渲染流程与优化
  10. 在你的网站中使用 AdSense广告
  11. java之mybatis之缓存
  12. $(function() {});和$(document).ready(function() {});区别
  13. 10万字208道Java经典面试题总结(附答案)
  14. linux -IOMMU
  15. oppo手机鸿蒙系统安装教程,oppo手机怎么刷机的步骤如下
  16. javascript有效的anagram挑战
  17. USYD悉尼大学DATA1002 详细作业解析Module6
  18. Java爬取frame的课程表_超级课程表一键提取课程功能app及课表静态网页内容
  19. Android 一定要培训吗,安卓开发需要学什么2
  20. 贪婪洞窟2服务器维护,12月24日贪婪洞窟2停服维护公告_贪婪洞窟2更新了什么_3DM手游...

热门文章

  1. 不止蔡徐坤,程序员也越努力越幸运?你是练习时长几年的程序员?
  2. antdesign卡片_10分钟精通Ant Design Form表单
  3. 关于android的sqlite问题,阳光沙滩-android studio的sqlite使用出现问题,是什么情况呢?...
  4. 国内星载光学卫星详解
  5. C语言 二分法查找与递归二分法查找
  6. Chino with Ciste
  7. depot_tools window 安装流程
  8. 【ROS入门学习01| ROS命令行工具的使用】
  9. 小恐龙游戏挑战:第11天-简单画好小恐龙并上色
  10. 使用phpExcelReader读取excel文件