mybatis-一对一的关联查询有两种配置方式

1、嵌套结果:

(mybatis-standalone - MyBatisTest - testSelectBlogWithAuthorResult ())

<!-- 根据文章查询作者,一对一查询的结果,嵌套查询-->
<resultMap id="BlogWithAuthorResultMap"
	type="com.leon.domain.associate.BlogAndAuthor">
	<id column="bid" property="bid" jdbcType="INTEGER"/>
	<result column="name" property="name" jdbcType="VARCHAR"/>
	<!-- 联合查询,将author 的属性映射到ResultMap -->
	<association property="author" javaType="com.leon.domain.Author">
		<id column="author_id" property="authorId"/>
		<result column="author_name" property="authorName"/>
	</association>
</resultMap>

2、嵌套查询:

(mybatis-standalone - MyBatisTest - testSelectBlogWithAuthorQuery ())

<!-- 另一种联合查询(一对一)的实现,但是这种方式有“N+1”的问题-->
<resultMap id="BlogWithAuthorQueryMap" type="com.leon.domain.associate.BlogAndAuthor">
	<id column="bid" property="bid" jdbcType="INTEGER"/>
	<result column="name" property="name" jdbcType="VARCHAR"/>
	<association property="author" javaType="com.leon.domain.Author"
		column="author_id" select="selectAuthor"/> <!-- selectAuthor 定义在下面-->
</resultMap>
<!-- 嵌套查询-->
<select id="selectAuthor" parameterType="int" resultType="com.leon.domain.Author">
	select author_id authorId, author_name authorName
	from author where author_id = #{authorId}
</select>

其中第二种方式:嵌套查询,由于是分两次查询,当我们查询了员工信息之后,会再发送一条SQL 到数据库查询部门信息。

我们只执行了一次查询员工信息的SQL(所谓的1),如果返回了N 条记录,就会再发送N 条到数据库查询部门信息(所谓的N),这个就是我们所说的N+1 的问题。这样会白白地浪费我们的应用和数据库的性能。

如果我们用了嵌套查询的方式,怎么解决这个问题?能不能等到使用部门信息的时候再去查询?这个就是我们所说的延迟加载,或者叫懒加载。

在MyBatis 里面可以通过开启延迟加载的开关来解决这个问题。

在settings 标签里面可以配置:

<!--延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。默认false -->
<setting name="lazyLoadingEnabled" value="true"/>
<!--当开启时,任何方法的调用都会加载该对象的所有属性。默认false,可通过select 标签的
fetchType 来覆盖-->
<setting name="aggressiveLazyLoading" value="false"/>
<!-- Mybatis 创建具有延迟加载能力的对象所用到的代理工具,默认JAVASSIST -->
<setting name="proxyFactory" value="CGLIB" />

lazyLoadingEnabled 决定了是否延迟加载。

aggressiveLazyLoading 决定了是不是对象的所有方法都会触发查询。

先来测试一下(也可以改成查询列表):

1、没有开启延迟加载的开关,会连续发送两次查询;

2 、开启了延迟加载的开关, 调用blog.getAuthor() 以及默认的(equals,clone,hashCode,toString)时才会发起第二次查询,其他方法并不会触发查询,比如blog.getName();

3、如果开启了aggressiveLazyLoading=true,其他方法也会触发查询,比如blog.getName()。

问题:为什么可以做到延迟加载?blog.getAuthor(),只是一个获取属性的方法,里面并没有连接数据库的代码,为什么会触发对数据库的查询呢?

我怀疑:blog 根本不是Blog 对象,而是被人动过了手脚!

把这个对象打印出来看看:

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

果然不对:

class com.leon.domain.associate.BlogAndAuthor_$$_jvst70_0

这个类的名字后面有jvst,是JAVASSIST 的缩写。原来到这里带延迟加载功能的对象blog 已经变成了一个代理对象,那到底什么时候变成代理对象的?我们后面在看源码的时候再去分析,这个也先留一个作业给大家。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值