• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • MsSql
  • Mysql
  • oracle
  • MariaDB
  • DB2
  • SQLite
  • PostgreSQL
  • MongoDB
  • Redis
  • Access
  • 数据库其它
  • sybase
  • HBase
您的位置:首页 > 数据库 >数据库其它 > Mybatis查询延迟加载详解及实例

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

作者: 字体:[增加 减小] 来源:互联网 时间:2017-05-11

通过本文主要向大家介绍了mybatis配置文件详解,mybatis注解详解,mybatis逆向工程详解,mybatis详解,mybatis二级缓存详解等相关知识,希望本文的分享对您有所帮助

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

1.1     启用延迟加载

       Mybatis的延迟加载是针对嵌套查询而言的,是指在进行查询的时候先只查询最外层的SQL,对于内层SQL将在需要使用的时候才查询出来。Mybatis的延迟加载默认是关闭的,即默认是一次就将所有的嵌套SQL一并查了将对象所有的信息都查询出来。开启延迟加载有两种方式。

       第一种是在对应的<collection>或<association>标签上指定fetchType属性值为“lazy”。如下示例中我们在查询id为selectByPrimaryKey的查询时会返回BaseResultMap,在BaseResultMap中,我们指定了属性“nodes”是一个集合类型的,而且是需要通过id为selectNodes的查询进行查询的,我们指定了该查询的fetchType为lazy,即延迟加载。

  <resultMap id="BaseResultMap" type="com.elim.learn.mybatis.model.SysWfProcess">

   <id column="id" jdbcType="INTEGER" property="id" />

   <result column="template_id" jdbcType="INTEGER" property="templateId" />

   <result column="creator" jdbcType="INTEGER" property="creator" />

   <result column="create_time" jdbcType="TIMESTAMP" property="createTime" />

   <collection property="nodes" column="id"

    ofType="com.elim.learn.mybatis.model.SysWfNode" select="selectNodes" fetchType="lazy"/>

  </resultMap>

  <resultMap id="SysWfNodeResult" type="com.elim.learn.mybatis.model.SysWfNode">

   <id column="id" jdbcType="INTEGER" property="nodeId" />

   <result column="process_id" jdbcType="INTEGER" property="processId" />

   <result column="node_code" jdbcType="VARCHAR" property="nodeCode" />

   <result column="node_name" jdbcType="VARCHAR" property="nodeName" />

  </resultMap>

  <select id="selectByPrimaryKey" parameterType="java.lang.Integer"

   resultMap="BaseResultMap">

   select

   <include refid="Base_Column_List" />

   from sys_wf_process

   where id = #{id,jdbcType=INTEGER}

  </select>

  <select id="selectNodes"

   resultMap="SysWfNodeResult">

   select id, process_id, node_code, node_name from sys_wf_node

   where process_id=#{id}

  </select>

</div>

       第二种是开启全局的延迟加载。通过在Mybatis的配置文件的<settings>标签下加上如下配置可开启全局的延迟加载。开启了全局的延迟加载后我们就无需再在各个嵌套的子查询上配置延迟加载了,如果有某一个嵌套的子查询是不需要延迟加载的,可以设置其fetchType=”eager”。设置在嵌套查询上的fetchType可以覆盖全局的延迟加载设置。

   <setting name="lazyLoadingEnabled" value="true"/>
</div>

1.2     分析

       Mybatis的查询结果是由ResultSetHandler接口的handleResultSets()方法处理的。ResultSetHandler接口只有一个实现,DefaultResultSetHandler。有兴趣的朋友可以去看一下它的源码,看一下它是如何处理结果集的。对于本文的主题,延迟加载相关的一个核心的方法就是如下这个创建返回结果对象的方法。

 private Object createResultObject(ResultSetWrapper rsw, ResultMap resultMap, ResultLoaderMap lazyLoader, String columnPrefix) throws SQLException {

  final List<Class<?>> constructorArgTypes = new ArrayList<Class<?>>();

  final List<Object> constructorArgs = new ArrayList<Object>();

  final Object resultObject = createResultObject(rsw, resultMap, constructorArgTypes, constructorArgs, columnPrefix);

  if (resultObject != null && !typeHandlerRegistry.hasTypeHandler(resultMap.getType())) {

   final List<ResultMapping> propertyMappings = resultMap.getPropertyResultMappings();

   for (ResultMapping propertyMapping : propertyMappings) {

    // issue gcode #109 && issue #149

    if (propertyMapping.getNestedQueryId() != null && propertyMapping.isLazy()) {

     return configuration.getProxyFactory().createProxy(resultObject, lazyLoader, configuration, objectFactory, constructorArgTypes, constructorArgs);

    }

   }

  }

  return resultObject;

 }

</div>

        在上面方法中我们可以看到Mybatis先是根据正常情况创建一个返回类型对应的对象。当我们的ResultMap是包含子查询的时候,其会在我们正常返回类型对象的基础上创建对应的代理对象。对,你没有看错,就是我们的直接结果是代理对象,而不是子查询对应的属性是代理对象。默认是基于JavassistProxyFactory类创建的代理对象。可以通过Mybatis的全局配置proxyFactory来更改,可选值是CGLIB和JAVASSIST,默认是后者。需要使用CGLIB代理时注意加入CGLIB的包。

   <setting name="proxyFactory" value="CGLIB"/>
</div>

       回过头来看我们之前的那个延迟加载的配置,我们的一个查询返回的是SysWfProcess类型的对象,其有一个SysWfNode集合类型的nodes属性,nodes属性是通过一个子查询查出来的,而且是延迟加载。这个时候我们来进行以下测试。

 @Test

  public void testLazyLoad1() {

   SysWfProcessMapper mapper = this.session.getMapper(SysWfProcessMapper.class);

   SysWfProcess process = mapper.selectByPrimaryKey(1);

   System.out.println(process.getClass());

  }
 

</div>

       这个时候你会发现,上面的测试代码的输出结果是一个代理类,而不是我们自己的com.elim.learn.mybatis.model.SysWfProcess类型。另外如果你启用了日志输出,并且是打印的DEBUG日志,你会看到Mybatis是发了两条SQL进行查询的。

2016-12-23 15:43:21,131 DEBUG [main] (BaseJdbcLogger.java:145) - ==> Preparing: select id, template_id, creator, create_time from sys_wf_process where id = ?

2016-12-23 15:43:21,156 DEBUG [main] (BaseJdbcLogger.java:145) - ==> Parameters: 1(Integer)

2016-12-23 15:43:21,269 DEBUG [main] (BaseJdbcLogger.java:145) - <==   Total: 1

class com.elim.learn.mybatis.model.SysWfProcess_$$_jvstc25_0

2016-12-23 15:43:21,271 DEBUG [main] (BaseJdbcLogger.java:145) - ==> Preparing: select id, process_id, node_code, node_name from sys_wf_node where process_id=?

2016-12-23 15:43:21,272 DEBUG [main] (BaseJdbcLogger.java:145) - ==> Parameters: 1(Integer)

2016-12-23 15:43:21,274 DEBUG [main] (BaseJdbcLogger.java:145) - <==   Total: 2

 

</div>

       但是如果我们把最后一个System.out.println()去掉,也就是说我们只是从数据库中查询出SysWfProcess对象,而不使用它的时候,通过查看日志输出你会发现Mybatis又只会发送一条SQL,即只是查询出SysWfProcess的信息。这是为什么呢?

 1.3     aggressiveLazyLoading

       这是因为当我们启用了延迟加载时,我们的查询结果返回的是一个代理对象,当我们访问该代理对象的方法时,都会触发加载所有的延迟加载的对象信息。这也就可以很好的解释上面的场景。但是如果是这样的设计,貌似Mybatis的延迟加载作用不大。但事实并非如此,这只是Mybatis的一个默认策略,我们可以通过Mybatis的全局配置aggressiveLazyLoading来改变它,默认是true,表示延迟加载时将在第一次访问代理对象的方法时就将全部的延迟加载对象加载出来。当设置为false时则会在我们第一次访问延迟加载的对象的时候才会从数据库加载对应的数据。注意在延迟对象未从数据库加载出来前,我们对应延迟对象的属性将是null,因为你没有对它赋值。

  <setting name="aggressiveLazyLoading" value="fasle"/>
</div>

1.4     lazyLoadTriggerMethods

       那如果我们设置了aggressiveLazyLoading=”false”,但又希望在调用某些方法之前把所有的延迟对象都从数据库加载出来,怎么办呢?这个时候我们可以通过lazyLoadTriggerMethods参数来指定需要加载延迟对象的方法

分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • mybatis 项目配置文件实例详解
  • Mybatis查询延迟加载详解及实例

相关文章

  • 2017-05-11如何让SQL运行得更快
  • 2017-05-11存储过程返回数组对象示例代码
  • 2017-05-11在PostgreSQL中使用日期类型时一些需要注意的地方
  • 2017-05-11关于SQL注入中文件读写的方法总结
  • 2017-05-11在CRUD操作中与业务无关的SQL字段赋值的方法
  • 2017-05-11只有两个字段用一个sql语句查询出某个学生的姓名、成绩以及在表中的排名
  • 2017-05-11sqlserver、Mysql、Oracle三种数据库的优缺点总结
  • 2017-05-11SQL Prompt--绝好的SQL语法提示工具
  • 2017-09-08使用.pgpass密码文件,通过psql登录greenplum
  • 2017-05-11Instagram提升PostgreSQL性能的五个技巧

文章分类

  • MsSql
  • Mysql
  • oracle
  • MariaDB
  • DB2
  • SQLite
  • PostgreSQL
  • MongoDB
  • Redis
  • Access
  • 数据库其它
  • sybase
  • HBase

最近更新的内容

    • 在telnet下操作memcache详解(操作命令详解)
    • mybatis keyproperty 总是返回1
    • MySQL与Oracle差异比较之三 函数
    • 数据库分页查询方法
    • redis密码设置、访问权限控制等安全设置
    • Win2003系统安装SQL Sever2000后1433端口未开放的解释
    • HTTP头注入漏洞之SQL注入
    • 关于SQL注入中文件读写的方法总结
    • Spring集成MyBatis完整实例(分享)
    • 几种常用DB驱动和DB连接串小结

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有