MyBatis延迟加载策略深入探究

目录
  • 分步查询的优点
  • 在主配置文件当中设置延迟加载
  • 在studentDao.xml当中设置分步查询
  • 测试结果
  • 如何使用
  • 延迟加载的好处

有两种写法来表示查询信息,分别是链表查询和分步查询的方法。那么既然我么能用一个SQL语句能够执行完,那为什么还要分开来写呢?

原因很简单:可以发现如果我们把他们连在一起那么他们就是一个多表查询语句,如果不放在一起执行,那那就是单独一个表的查询语句。但是这需要我们设置mybatis的延迟加载(懒加载)

分步查询的优点

**可以实现延迟加载,**但是必须在核心配置文件中设置全局配置信息

lazyLoadingEnabled:延迟加载的全局开关。当开启时,所有关联对象都会延迟加载

aggressiveLazyLoding:当开启时,任何方式的调用都会加载该对象的所有属性。否则,该属性会按需加载 ,此时就可以实现按需加载,需要获取的数据是什么,就只会执行相应的sql.此时会通过association和collection中的fetchType属性设置当前的分步查询是否使用懒加载

fetchType=“lazy(延迟加载) | eager(立即加载)”

在主配置文件当中设置延迟加载

延迟加载:在SqlMapConfig.xml中配置延迟加载文件

<settings>
    <setting name="logImpl" value="STDOUT_LOGGING" />  <!-- 打印日志到控制台上 -->
    <setting name="lazyLoadingEnabled" value="true"/>
    <setting name="aggressiveLazyLoading" value="false"/>   <!-- false才会按需加载,不开启调用所有的对象 -->
</settings>

在studentDao.xml当中设置分步查询

测试结果

此时开启了懒加载,实现了分布查询

如何使用

public class UserDO {
  private Integer userId;
  private String username;
  private String password;
  private String nickname;
  private List<PermitDO> permitDOList;
  public UserDO() {}
}
<resultMap id="BaseMap" type="org.apache.ibatis.study.entity.UserDO">
    <id column="user_id" jdbcType="INTEGER" property="userId" />
    <result column="username" jdbcType="VARCHAR" property="username" />
    <result column="password" jdbcType="VARCHAR" property="password" />
    <result column="nickname" jdbcType="VARCHAR" property="nickname"/>
    <collection property="permitDOList" column="user_id" select="getPermitsByUserId"
     fetchType="lazy">
    </collection>
</resultMap>
  <resultMap id="PermitBaseMap" type="org.apache.ibatis.study.entity.PermitDO">
    <id column="id" jdbcType="INTEGER" property="id"/>
    <result column="code" jdbcType="VARCHAR" property="code"/>
    <result column="name" jdbcType="VARCHAR" property="name"/>
    <result column="type" jdbcType="TINYINT" property="type"/>
    <result column="pid" jdbcType="INTEGER" property="pid"/>
  </resultMap>
   <select id="getByUserId2" resultMap="BaseMap">
    select * from user
    where user_id = #{userId}
  </select>
  <select id="getPermitsByUserId" resultMap="PermitBaseMap">
    select p.*
    from user_permit up
    inner join permit p on up.permit_id = p.id
    where up.user_id = #{userId}
  </select>

通过fetchType=lazy指定子查询getPermitsByUserId使用懒加载,这样的话就不用管全局配置lazyLoadingEnabled是true还是false了。当然这里可以直接用多表关联查询不使用子查询,使用方法在这篇文章

测试代码

public class Test {
  public static void main(String[] args) throws IOException {
    try (InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml")) {
      // 构建session工厂 DefaultSqlSessionFactory
      SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
      SqlSession sqlSession = sqlSessionFactory.openSession();
      UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
      UserDO userDO = userMapper.getByUserId2(1);
      System.out.println(userDO);
    }
  }
}

结果如下,打了断点可以看到原userDO对象已被代理并且permitDOList是null需要调用get方法才会去查询拿到值,咳咳这边之前直接运行显示是已经把permitDOList查询出来了,想了半天啥原因后来才发现println会调用userDO对象的toString方法,而toString方法也会走代理方法直接去调用子查询的

延迟加载的好处

延迟加载主要能解决mybatis的N+1问题,什么是N+1问题其实叫1+N更为合理,以上面的业务例子来说就是假设一次查询出来10000个用户,那么还需要针对这10000个用户使用子查询getPermitsByUserId获取每个用户的权限列表,需要10000次查询,总共10001次,真实情况下你可能并不需要每个子查询的结果,这样就浪费数据库连接资源了。如果使用延迟加载的话就相当于不用进行这10000次查询,因为它是等到你真正使用的时候才会调用子查询获取结果。

到此这篇关于MyBatis延迟加载策略深入探究的文章就介绍到这了,更多相关MyBatis延迟加载内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • mybatis中延迟加载Lazy策略的方法

    lazy策略原理:只有在使用查询sql返回的数据是才真正发出sql语句到数据库,否则不发出(主要用在多表的联合查询) 1.一对一延迟加载: 假设数据库中有person表和card表:其中person表中有字段pid,pname,page,psex,cid,card表中有字段cid,cnum; 假设要查询某个人的姓名和身份证号码: 原理:在查询姓名时,实际本没有查询出身份证号码的信息,只有当前台使用身份证号时才发出对card的查询,需要查询出身份证号码是采取查询的一种策略: 实现实例: 实现步骤:

  • MyBatis延迟加载策略深入探究

    目录 分步查询的优点 在主配置文件当中设置延迟加载 在studentDao.xml当中设置分步查询 测试结果 如何使用 延迟加载的好处 有两种写法来表示查询信息,分别是链表查询和分步查询的方法.那么既然我么能用一个SQL语句能够执行完,那为什么还要分开来写呢? 原因很简单:可以发现如果我们把他们连在一起那么他们就是一个多表查询语句,如果不放在一起执行,那那就是单独一个表的查询语句.但是这需要我们设置mybatis的延迟加载(懒加载) 分步查询的优点 **可以实现延迟加载,**但是必须在核心配置文

  • mybatis 延迟加载的深入理解

    什么是延迟加载 延迟加载又叫懒加载,也叫按需加载,也就是说先加载主信息,需要的时候,再去加载从信息.代码中有查询语句,当执行到查询语句时,并不是马上去DB中查询,而是根据设置的延迟策略将查询向后推迟. 什么时候会执行延迟加载 配置之后在对关联对象进行查询时使用延迟加载. 延迟加载策略 直接加载 遇到代码中查询语句,马上到DB中执行select语句进行查询.(这种只能用于多表单独查询) 侵入式延迟加载 将关联对象的详情(具体数据,如id.name)侵入到主加载对象,作为主加载对象的详情的一部分出现

  • 解析Mybatis延迟加载问题

    延迟加载问题 MyBatis针对关联表中的数据支持延迟加载.延迟加载其实就是将数据加载时机推迟,比如推迟嵌套查询的执行时机. 延迟加载可以实现先查询主表,按需实时做关联查询,返回关联表结果集,一定程度上提高了效率. <settings> <!-- 启用延迟加载特性,不配置默认关闭该特性--> <setting name="lazyLoadingEnabled" value="true" /> <!-- 按需加载: false

  • MyBatis延迟加载与立即加载案例教程

    MyBatis入门-延迟加载与立即加载 加载策略 延迟加载 延迟加载(lazy load)是(也称为懒加载)Hibernate3关联关系对象默认的加载方式,延迟加载机制是为了避免一些无谓的性能开销而提出来的,所谓延迟加载就是当在真正需要数据的时候,才真正执行数据加载操作.延迟加载,可以简单理解为,只有在使用的时候,才会发出sql语句进行查询. 需要在主配置文件开启加载策略,子配置文件使用collection属性 立即加载 所谓立即加载就是查询时,所有的相关数据一次被读取出来,而不是分N次. 一对

  • MyBatis 延迟加载、一级缓存、二级缓存(详解)

    使用ORM框架我们更多的是使用其查询功能,那么查询海量数据则又离不开性能,那么这篇中我们就看下mybatis高级应用之延迟加载.一级缓存.二级缓存.使用时需要注意延迟加载必须使用resultMap,resultType不具有延迟加载功能. 一.延迟加载 延迟加载已经是老生常谈的问题,什么最大化利用数据库性能之类之类的,也懒的列举了,总是我一提到延迟加载脑子里就会想起来了Hibernate get和load的区别.OK,废话少说,直接看代码. 先来修改配置项xml. 注意,编写mybatis.xm

  • MyBatis拦截器原理探究

    MyBatis拦截器介绍 MyBatis提供了一种插件(plugin)的功能,虽然叫做插件,但其实这是拦截器功能.那么拦截器拦截MyBatis中的哪些内容呢? 我们进入官网看一看: MyBatis 允许你在已映射语句执行过程中的某一点进行拦截调用.默认情况下,MyBatis 允许使用插件来拦截的方法调用包括: Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed) P

  • java工程师进阶之MyBatis延迟加载的使用

    目录 什么是延迟加载? 如何使用延迟加载? 1.在 config.xml 中开启延迟加载 2.将多表关联查询拆分成多个单表查询 什么是延迟加载? 延迟加载也叫懒加载.惰性加载,使⽤延迟加载可以提⾼程序的运行效率,针对于数据持久层的操作, 在某些特定的情况下去访问特定的数据库,在其他情况下可以不访问某些表,从⼀定程度上减少了 Java 应⽤与数据库的交互次数. 查询学⽣和班级的时,学生和班级是两张不同的表,如果当前需求只需要获取学shengsheng的信息,那么查询学 ⽣单表即可,如果需要通过学⽣

  • Mybatis延迟加载和缓存深入讲解

    一.Mybatis中的延迟加载 1.延迟加载背景:Mybatis中Mapper配置文件中的resultMap可以实现高级映射(使用association.collection实现一对一及一对多(多对多)映射),同样的association.collection具备延迟加载功能.所谓延迟加载,就是先单表查询,需要时再从关联表去关联查询(同样也可能只是是单表查询),大大单表查询速度更快,所以可以间接的提高数据库性能 2.在mybatis核心配置文件中配置,其中lazyLoadingEnabled表示

  • Mybatis延迟加载的实现方式

    1.概念: MyBatis中的延迟加载,也称为懒加载,是指在进行表的关联查询时,按照设置延迟规则推迟对关联对象的select查询.例如在进行一对多查询的时候,只查询出一方,当程序中需要多方的数据时,mybatis再发出sql语句进行查询,这样子延迟加载就可以的减少数据库压力.MyBatis 的延迟加载只是对关联对象的查询有迟延设置,对于主加载对象都是直接执行查询语句的. 2.加载时机: 直接加载:执行完对主加载对象的 select 语句,马上执行对关联对象的 select 查询.侵入式延迟: 执

  • Mybatis查询延迟加载详解及实例

    Mybatis查询延迟加载详解及实例 1.1     启用延迟加载 Mybatis的延迟加载是针对嵌套查询而言的,是指在进行查询的时候先只查询最外层的SQL,对于内层SQL将在需要使用的时候才查询出来.Mybatis的延迟加载默认是关闭的,即默认是一次就将所有的嵌套SQL一并查了将对象所有的信息都查询出来.开启延迟加载有两种方式. 第一种是在对应的<collection>或<association>标签上指定fetchType属性值为"lazy".如下示例中我们

随机推荐