MyBatis的resultMap支持三种级联方式:一对一关系(assocation)、一对多关系(collection)、鉴别器(discriminator)。 使用级联方式获取数据时,数据是及时加载的,会带来性能问题。有些时候想需要数据的时候再按需加载,可以采用MyBatis延迟加载。
举个例子,查询学生信息的时候关联查询学生成绩。如果先查询学生信息即可满足要求,当需要查询成绩时再查询成绩信息。这种按需查询就是延迟加载。
延迟加载配置
在mybatis的配置中有两个全局参数 lazyLoadingEnabled 和 aggressiveLazyLoading :
设置项 | 描述 | 可选值 | 默认值 |
---|---|---|---|
lazyLoadingEnabled | 全局懒加载设置 | true | false | false |
aggressiveLazyLoading | 对任意延迟属性的调用会使带有延迟加载属性的对象完整加载 | true | false | true |
mybatis默认没有开启延迟加载,需要在mybatis-config.xml的settings进行如下配置。
1 |
|
成绩信息类
1 |
|
学生信息类
1 |
|
Mapper配置
1 |
|
上面的配置已经能实现延迟加载了。下面我们来看一下效果:
从图中可以看出,执行mapper.getList()方法只查询了学生信息,并没有查询成绩,而是在下面循环的时候才去查的成绩。
上面的配置是全局配置,不能指定哪些属性可以立即加载,哪些属性可以延迟加载,不太灵活。MyBatis有局部延迟加载的功能。可以在 association、collection和discriminator 元素上加上fetchType 属性,它有两个取值范围,即eager(立即加载)和lazy(延迟加载),默认值是eager。
实现原理
延迟加载的实现原理是通过动态代理来实现的。默认情况下,MyBatis在3.3或者以上版本时,才采用JAVASSIST的动态代理,低版本是CGLIB。它生成一个动态代理对象,里面保存着相关的参数和sql, 一旦我们使用这个代理对象的方法,它就会进入到动态代理对象的方法里,通过发送SQL和参数,把对应的结果从数据库里查找回来,这便是其实现原理。