什么是延迟加载
延迟加载的条件:resultMap可以实现高级映射(使用association、collection实现一对一及一对多映射),association、collection具备延迟加载功能。
延迟加载的好处:
先从单表查询、需要时再从关联表去关联查询,大大提高 数据库性能,因为查询单表要比关联查询多张表速度要快。
延迟加载的实例:
如果查询订单并且关联查询用户信息。如果先查询订单信息即可满足要求,当我们需要查询用户信息时再查询用户信息。把对用户信息的按需去查询就是延迟加载。
如何开启延迟加载功能
Mybatis的延迟加载功能默认是关闭的
需要在SqlMapConfig.xml文件中通过setting标签配置来开启延迟加载功能
开启延迟加载的属性:
lazyLoadingEnabled:全局性设置懒加载。如果设为‘false’,则所有相关联的都会被初始化加载。默认为false
aggressiveLazyLoading:当设置为‘true’的时候,懒加载的对象可能被任何懒属性全部加载。否则,每个属性都按需加载。默认为true
配置
<settings>
<!-- 打开延迟加载开关 -->
<setting name="lazyLoadingEnabled" value="true"/>
<!-- 将积极加载改为消极加载即按需加载 -->
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
Mapper文件
现在我们要实现一个功能:查询orders表中所有的信息,并根据每一行中的user_id从user表中查询user的信息.
SELECT orders.*,`user`.* from orders,`user` where orders.user_id = `user`.id
但是有时候我们只需要orders的数据,而暂时不需要user的数据,等到有人要查询的时候再加载user的数据.
即先执行
SELECT orders.* from orders
等需要的时候再执行
SELECT user.* from user where id = orders.user_id
我们可以使用resultMap中的association来实现
第一个statement
<select id="OrderUserLazyLoadingResult" resultMap="OrderUserLazyLoadingResultMap">
select * from orders
</select>
第二个statement
<select id="findUserById" parameterType="int" resultType="mybatis.com.entity.User">
select * from user where id = #{value}
</select>
现在整合两个statement来实现延迟加载
<resultMap type="mybatis.com.entity.Orders" id="OrderUserLazyLoadingResultMap">
<!-- 配置映射的订单信息 -->
<id column="id" property="id"/>
<result column="user_id" property="user_id"/>
<result column="num" property="num"/>
<result column="createtime" property="createtime"/>
<result column="note" property="note"/>
<!-- 配置映射的用户信息 -->
<!--
实现用户的延迟加载
select:指定延迟加载需要执行的statement的id(即查询用户的<select></select>)
column:订单信息中关联用户查询的列,即user_id,要传入findUserById的参数
-->
<association property="user" javaType="mybatis.com.entity.User" select="findUserById" column="user_id">
</association>
</resultMap>
测试
@Test
public void findOrderUser() throws IOException{
String resource = "SqlMapConfig.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
OrdersMapperCustom ordersMapperCustom = sqlSession.getMapper(OrdersMapperCustom.class);
List<Orders> orders = ordersMapperCustom.OrderUserLazyLoadingResult();
sqlSession.close();
}
日志如下:
从日志可以看出只执行了select * from orders 而 没有执行select * from user
总结
不使用mybatis提供的association及collection中的延迟加载功能,如何实现延迟加载??
实现方法如下:
定义两个mapper方法:
1、查询订单列表
2、根据用户id查询用户信息
实现思路:
先去查询第一个mapper方法,获取订单信息列表
在程序中(service),按需去调用第二个mapper方法去查询用户信息。