1.引子

mybatis的延迟加载,主要应用于一个实体类中有复杂数据类型的属性,包括一对一和一对多的关系(在xml中用collection、association标签标识)。这个种属性往往还对应着另一个数据表,而实际查询的需求不一定需要这个的表的数据,那么此时延迟加载相对于连表查询就有很大的优势,达到了按需加载的目的。这对提高访问速度和降低系统资源耗费有着很大的意义。

2.连表查询

背景: 用户实体类User中包含有一个为角色实体类Role类型的属性role,及对应角色表主键id的roleUser整型属性

需求:用角色id和用户id列表,查找出用户信息,及其所角色名称

分析: 角色名称不在用户表中,用户表中只有角色表的主键id,那么此就必须要根据roleUser到角色表中再查询。为了减少查询次数,实际上我们进行连表查询。

实体类User中的部分属性

  1. private Integer id; // id
  2. private String userCode; // 用户编码
  3. private String userName; // 用户名称
  4. private String userPassword; // 用户密码
  5. private Integer userRole; // 用户角色id,和角色表smbms_role的id字段关联对应
  6. private Role role; //角色 一对一 对应关系
  7. private List<Address> addressList; //地址 一对多

实体类Role中的属性

  1. private Integer id; // id
  2. private String roleCode; // 角色编码
  3. private String roleName; // 角色名称
  4. private Integer createdBy; // 创建者
  5. private Date creationDate; // 创建时间
  6. private Integer modifyBy; // 更新者
  7. private Date modifyDate;// 更新时间

xml中的sql语句映射文件

  1. <!-- 演示 一对一 association 的连表查询 start -->
  2.  
  3. <resultMap type="Role" id="roleMap">
  4. <id property="id" column="r_id" />
  5. <result property="roleCode" column="roleCode" />
  6. <result property="roleName" column="roleName" />
  7. </resultMap>
  8. <resultMap type="User" id="userRoleResult">
  9. <id property="id" column="id" />
  10. <result property="userCode" column="userCode" />
  11. <result property="userName" column="userName" />
  12. <association property="role" javaType="Role" resultMap="roleMap" />
  13. </resultMap>
  14. <!-- 根据用户表中角色id 和角色表做联表查询 -->
  15. <select id="getUserListByRoleId" parameterType="int" resultMap="userRoleResult">
  16. select u.* ,r.id as r_id,r.roleCode,r.roleName from
  17. smbms_user
  18. u,smbms_role r
  19. where u.userRole = #{userRoleId} and u.userRole = r.id
  20. </select>
  21.  
  22. <!-- 演示 一对一 association 的连表查询 end -->

测试方法

  1. @Test
  2. public void selectUserByIdsAndRoleId()
  3. {
  4. List<User> users = sqlSession.getMapper(UserMapper.class).selectUserByIdsAndRoleId(3, Arrays.asList(4, 3, 7,12));
  5. for (User userElement : users)
  6. {
  7. System.out.println(userElement);
  8. }
  9. }

3. 延迟加载

1)延迟加载配置

延迟加载可以在主配置文件mybatis-config.xml中配置,在这里的配置是全局配置,默认对所有查询SQL进行延迟加载处理。

  1. <settings>
  2. <!--启用延迟加载 -->
  3. <setting name="lazyLoadingEnabled" value="true" />
  4. <!--关闭积极加载 -->
  5. <setting name="aggressiveLazyLoading" value="false" />
  6. </settings>

另外如果对全局配置不满意,可以在具体的SQL映射语句中添加collect或assocation标签中添加属性fetchType="lazy"(延迟加载)或fetchType="eager"(立即加载),

此处SQL加载方式将覆盖全局配置中的SQL加载方式,如伪代码

  1. <collection property="addressList"
  2. ofType="Address" column="id"
  3. fetchType="lazy|eager"/>

2)延迟加载SQL映射

背景: 用户实体类User中包含有一个List集合且元素类型为Address的属性addressList,用户表的id与地址表的userId有对应的主外键关系

需求:使用用户id查找出用户信息及相关地址信息(但地址可能不会总是被使用)

分析: 地址信息不总会用到,如果某次查询刚好是这种情况,也就没有必要再去查询地址表了。这时就可以使用延迟加载技术,实现按需动态加载资源。

xml中的sql映射代码

  1. <!--演示 一对多 collection -->
  2. <resultMap type="User" id="userAddressResult">
  3. <id property="id" column="id" />
  4. <result property="userCode" column="userCode" />
  5. <result property="phone" column="phone" />
  6. <result property="userName" column="userName" />
  7. <!-- 在collection标签内需要注意这几个属性的设置
  8. 1."column"属性,此属性是两张表关联的关键,此字段的值能唯一确定另一张从表的对应记录行,此字段与从表的外键一一对应,此字段一般为主表的主键,
  9. 相当于连表查询中根据主外键建立两张的的关联关系,
  10. 如" from smbms_user u inner join smbms_address a on u.id = a.userId "
  11. 2."select"属性,此属性指定可能需要查询SQL的id,
  12. 3."fetchType"属性,指定为"lazy"(懒加载)实现延迟加载效果(若全局配置已配置过延迟加载,也可在此处不写此属性,
  13. mybatis也会默认读到全局配置中的延迟加载项),而"eager"表示立即加载
    4.ofType可以不写,lazyFindAddressListByUserId这个查询本身已经指定了返回数据类型
  14. -->
  15. <collection property="addressList" ofType="Address" column="id"
  16. select="lazyFindAddressListByUserId" fetchType="lazy" />
  17. </resultMap>
  18.  
  19. <!-- 延迟按需加载sql语句(即此sql可能不会使用) -->
  20. <select id="lazyFindAddressListByUserId" parameterType="int"
  21. resultType="Address">
  22. <!-- 如果确实需要此SQL查询,则上面<collection>标签中的"column='id'"
  23. 的id字段的对应值将传到此处的'userId=#{id}'中作为参数 ,进一步查询地址表smbms_address
  24. -->
  25. <!-- 若此处SQL确实被执行了,那么就相当于连表查询语句
  26. select a.* ,u.* from
  27. smbms_user u inner join smbms_address a on u.id = a.userId and u.id = #{id}
  28. -->
  29. select * from smbms_address where userId=#{id}
  30. </select>
  31.  
  32. <!-- 根据用户id获得 用户信息及多个地址信息 -->
  33. <select id="getAddressListByUserId" parameterType="Integer"
  34. resultMap="userAddressResult">
  35. select * from smbms_user where id = #{userId}
  36. </select>

3)延迟加载测试

不使用addressList地址信息的测试方法

  1. @Test
  2. public void getAddressListByUserId()
  3. {
  4. List<User> users = sqlSession.getMapper(UserMapper.class).getAddressListByUserId(5);
  5. for (User userElement : users)
  6. {
  7. //不使用addressList属性
  8. System.out.println(userElement.getPhone() +" "+userElement.getUserCode());
  9. // System.out.println(userElement);
  10. }
  11. }

控制台显示只有一个sql语句,则实际上只查询了一张用户表

使用addressList地址信息的测试方法

  1. @Test
  2. public void getAddressListByUserId()
  3. {
  4. List<User> users = sqlSession.getMapper(UserMapper.class).getAddressListByUserId(5);
  5. for (User userElement : users)
  6. {
  7. // 使用addressList属性
  8. // System.out.println(userElement.getPhone() +" "+userElement.getUserCode());
  9. System.out.println(userElement);
  10. }
  11. }

控制台显示只有两条sql语句,则实际上只先查询了用户表,再用用户id去查询地址表

4.总结

(1)连表查询,在任何情况下都要同时查询多张表的数据 ;  而延迟加载,只有在项目中确实使用到了另一个从表的数据,才会去查询第二(N)张表的数据。

(2)连表查询同时操作多张表,如果多张表的字段名有相同的,为了正确的将字段值映射到实体类的属性上,可能要给相同的字段名取一个别名,并对结果集进行相应的自定义映射;

而延迟加载相当于将一次连表查询操作分解为多次单表查询操作,既然是单表操作也就不可能出现字段名相同的情况,只要数据表的字段名和实体类的属性名按照同样的驼峰命名规则,就不需要对结果集进行自定义映射(mybatis会做默认的结果集映射)。

(3)对实体类的复杂数据类型属性做SQL映射,两者都会使用到"association"或"collection"标签。而连表查询、延迟加载在"association"或"collection"标签中的属性设置有些区别,延迟加载特别的要使用"column"、"select"、"fetchType"这三个属性。连表查询只能解决一对一的级联关系,而延迟加载既能处理一对一的级联,也能解决一对多的级联查询问题。

在mybatis框架中,延迟加载与连表查询的差异的更多相关文章

  1. 详解Java的MyBatis框架中SQL语句映射部分的编写

    这篇文章主要介绍了Java的MyBatis框架中SQL语句映射部分的编写,文中分为resultMap和增删查改实现两个部分来讲解,需要的朋友可以参考下 1.resultMap SQL 映射XML 文件 ...

  2. mybatis框架中XxxxMaper.xml的文件

    我们知道在mybatis框架中,config.xml中会关联到许多的XxxxMapper的xml文件,这些文件又对应着一个个的接口,来观察下这些xml文件 从以下这个文件为例子: <?xml v ...

  3. Mybatis 一对多延迟加载,并且子查询中与主表字段不对应 (19)

    Mybatis  一对多延迟加载,并且子查询中与主表字段不对应应用说明. 实现一对多关联(懒加载),一个教研组对应多个教师,既:教师的教研编号与教研组的教研编号关联,并且教师关联教研组外键与教研组编号 ...

  4. Mybatis框架中实现双向一对多关系映射

    学习过Hibernate框架的伙伴们很容易就能简单的配置各种映射关系(Hibernate框架的映射关系在我的blogs中也有详细的讲解),但是在Mybatis框架中我们又如何去实现 一对多的关系映射呢 ...

  5. mybatis逆向工程,实现join多表查询,避免多表相同字段名的陷阱

    ​ mybatis逆向工程,实现join多表查询,避免多表相同字段名的陷阱 ​ 前言:使用 mybatis generator 生成表格对应的pojo.dao.mapper,以及对应的example的 ...

  6. Oracle中把一张表查询结果插入到另一张表中

      1. 新增一个表,通过另一个表的结构和数据 create table XTHAME.tab1 as select * from DSKNOW.COMBDVERSION 2. 如果表存在: inse ...

  7. Spring+MyBatis框架中sql语句的书写,数据集的传递以及多表关联查询

    在很多Java EE项目中,Spring+MyBatis框架经常被用到,项目搭建在这里不再赘述,现在要将的是如何在项目中书写,增删改查的语句,如何操作数据库,以及后台如何获取数据,如何进行关联查询,以 ...

  8. 【mybatis】使用mybatis框架中踩过的坑

    好久没来记录一下自己的学习情况,最近都在学框架,今天来记录一下关于mybatis框架的学习过程中碰过的一些问题: 以下内容可能稍微有点凌乱,因为是把之前遇到过的错误或异常都集中一起了,不过我已经把问题 ...

  9. 优化mybatis框架中的查询用户记录数的案例

    通过对mybatis框架的中核心接口和类的分析,发现之前写的那个小demo是有问题的.现在对其进行部分优化. 如果存在多个功能的时候,势必会有很多重复的代码,如,创建sqlsession对象,关闭sq ...

随机推荐

  1. JNI操作二维数组

    之前的文章讲解了有关JNI使用方法,这篇文章进阶一点,介绍下JNI操作二维数组的方法.有了之前文章的操作JNI的方法,这里直接上代码了. Java代码部分 package com.testjni; p ...

  2. P2057 [SHOI2007]善意的投票 / [JLOI2010]冠军调查

    P2057 [SHOI2007]善意的投票 / [JLOI2010]冠军调查 拿来练网络流的qwq 思路:如果i不同意,连边(i,t,1),否则连边(s,i,1).好朋友x,y间连边(x,y,1)(y ...

  3. Cobalt Strike简单使用(9,29第十五天)

    本文转自:https://www.cnblogs.com/yuanshu/p/11616657.html 一.介绍: 后渗透测试工具,基于Java开发,适用于团队间协同作战,简称“CS”. CS分为客 ...

  4. POJ 1028:Web Navigation

    Web Navigation Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 30828   Accepted: 13821 ...

  5. MySLQ排序后标记排行

    查询排行及所有(表名.*) 1. ; AS top, customer.* FROM customer 2. AS top, customer.* ) r, customer ORDER BY cus ...

  6. 腾讯电话面试总结(IEG后台开发)

    1 Java面向对象:设计window画板的类框架.假设现在只有  直线.矩形.椭圆,怎么设计 2 Linux shell命令  定时怎么做 3 平时有问题经常访问那些网站 4 假设你现在是web网站 ...

  7. vue组件化应用构建

    组件系统是 Vue 的另一个重要概念,因为它是一种抽象,允许我们使用小型.独立和通常可复用的组件构建大型应用.仔细想想,几乎任意类型的应用界面都可以抽象为一个组件树: 在 Vue 里,一个组件本质上是 ...

  8. mac安装浏览器同步测试工具

    1.安装node.js (1)打开终端,输入以下命令安装Homebrew ruby -e “$(curl -fsSL https://raw.githubusercontent.com/Homebre ...

  9. CSS样式实现两个图片平分三角

    <div class='pageOption'> <a href='#' class='option' > <img src='http://imgsrc.hubbles ...

  10. solr8.0.0基本安装和在springboot中的基本使用(win10)

    1.下载solr 下载地址:http://archive.apache.org/dist/lucene/solr/ 该地址可以也可以下载以前的版本,我这边下载的solr-8.0.0.zip版本.下载完 ...