七 mybatis的延迟加载

1       延迟加载

1.1     什么是延迟加载

resultMap可以实现高级映射(使用association、collection实现一对一及一对多映射),association、collection具备延迟加载功能。

需求:

如果查询订单并且关联查询用户信息。如果先查询订单信息即可满足要求,当我们需要查询用户信息时再查询用户信息。把对用户信息的按需去查询就是延迟加载。

延迟加载:先从单表查询、需要时再从关联表去关联查询,大大提高 数据库性能,因为查询单表要比关联查询多张表速度要快。

1.2     使用association实现延迟加载

 打开延迟加载开关

在mybatis核心配置文件中配置:

lazyLoadingEnabled、aggressiveLazyLoading

设置项

描述

允许值

默认值

lazyLoadingEnabled

全局性设置懒加载。如果设为‘false’,则所有相关联的都会被初始化加载。

true | false

false

aggressiveLazyLoading

当设置为‘true’的时候,懒加载的对象可能被任何懒属性全部加载。否则,每个属性都按需加载。

true | false

true

1 <!-- 全局配置参数,需要时在配置 -->
2     <settings>
3         <!-- 打开延迟加载的开关,默认没有开启延迟加载 -->
4         <setting name="lazyLoadingEnabled" value="true"/>
5         <!-- 将递减加载改为消极加载,即按需要加载,默认为积极加载 -->
6         <setting name="aggressiveLazyLoading" value="false"/>
7     </settings>

1.2.1     需求

查询订单并且关联查询用户信息

1.2.2     mapper.xml

需要定义两个mapper的方法对应的statement。

1、只查询订单信息

SELECT * FROM orders

在查询订单的statement中使用association去延迟加载(执行)下边的satatement(关联查询用户信息)

 User.xml

1 <?xml version="1.0" encoding="UTF-8" ?>
2 <!DOCTYPE mapper
3 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
4 "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
5 <mapper namespace="test">
6     <select id="findUserById" parameterType="int" resultType="cn.itcast.po.User">
7         select * from user where id=#{value}
8     </select>
9 </mapper>

2、关联查询用户信息

         通过上边查询到的订单信息中user_id去关联查询用户信息

         使用User.xml中的findUserById

1     <!-- 查询订单关联查询用户,用户信息需要延迟加载 -->
2     <select id="findOrdersUserLazyLoading" resultMap="OrdersUserLazyLoading">
3         select * from orders
4     </select>

上边先去执行findOrdersUserLazyLoading,当需要去查询用户的时候再去执行findUserById,通过resultMap的定义将延迟加载执行配置起来。

1.2.3     延迟加载resultMap

使用association中的select指定延迟加载去执行的statement的id。

 1     <!-- 延迟加载的resultMap -->
 2     <resultMap type="cn.itcast.po.Orders" id="OrdersUserLazyLoading">
 3          <!--对订单信息进行映射配置  -->
 4         <id column="id" property="id"/>
 5         <result column="user_id" property="userId"/>
 6         <result column="number" property="number"/>
 7         <result column="createtime" property="createtime"/>
 8         <result column="note" property="note"/>
 9         
10       <!-- 实现对用户信息进行延迟加载
11          select:指定延迟加载需要执行的statement的id(是根据user_id查询用户信息的statement)
12                  要使用userMapper.xml中findUserById完成根据用户id(user_id)用户信息的查询,如果findUserById不在本mapper中需要前边加namespace
13          column:订单信息中关联用户信息查询的列,是user_id
14         
15          关联查询的sql理解为:
16          SELECT orders.*,
17    (SELECT username FROM USER WHERE orders.user_id = user.id)username,
18    (SELECT sex FROM USER WHERE orders.user_id = user.id)sex  FROM orders
19           -->
20           
21           <!-- 实现对用户信息进行延迟加载 -->
22         <association property="user" select="test.findUserById" javaType="cn.itcast.po.User" column="user_id"></association>
23     </resultMap>

1.2.4     mapper.java

1     //查询订单关联查询用户,用户信息是延迟加载
2     public List<Orders> findOrdersUserLazyLoading()throws Exception;

1.2.5     测试

1.2.5.1              测试思路:

1、执行上边mapper方法(findOrdersUserLazyLoading),内部去调用cn.itcast.mybatis.mapper.OrdersMapperCustom中的findOrdersUserLazyLoading只查询orders信息(单表)。

2、在程序中去遍历上一步骤查询出的List<Orders>,当我们调用Orders中的getUser方法时,开始进行延迟加载。

3、延迟加载,去调用UserMapper.xml中findUserbyId这个方法获取用户信息。

1.2.5.2              延迟加载配置

mybatis默认没有开启延迟加载,需要在SqlMapConfig.xml中setting配置。

在mybatis核心配置文件中配置:

lazyLoadingEnabled、aggressiveLazyLoading

设置项

描述

允许值

默认值

lazyLoadingEnabled

全局性设置懒加载。如果设为‘false’,则所有相关联的都会被初始化加载。

true | false

false

aggressiveLazyLoading

当设置为‘true’的时候,懒加载的对象可能被任何懒属性全部加载。否则,每个属性都按需加载。

true | false

true

在SqlMapConfig.xml中配置:

1 <!-- 全局配置参数,需要时在配置 -->
2     <settings>
3         <!-- 打开延迟加载的开关,默认没有开启延迟加载 -->
4         <setting name="lazyLoadingEnabled" value="true"/>
5         <!-- 将递减加载改为消极加载,即按需要加载 -->
6         <setting name="aggressiveLazyLoading" value="false"/>
7     </settings>

1.2.5.3           测试代码

 1     // 查询订单关联查询用户,用户信息使用延迟加载
 2     @Test
 3     public void testFindOrdersUserLazyLoading() throws Exception {
 4         SqlSession sqlSession = sqlSessionFactory.openSession();// 创建代理对象
 5         OrdersMapperCustom ordersMapperCustom = sqlSession
 6                 .getMapper(OrdersMapperCustom.class);
 7         // 查询订单信息(单表)
 8         List<Orders> list = ordersMapperCustom.findOrdersUserLazyLoading();
 9 
10         // 遍历上边的订单列表
11         for (Orders orders : list) {
12             // 执行getUser()去查询用户信息,这里实现按需加载
13             User user = orders.getUser();
14             System.out.println(user);
15         }
16 
17     }

1.2.6     延迟加载思考

不使用mybatis提供的association及collection中的延迟加载功能,如何实现延迟加载??

实现方法如下:

定义两个mapper方法:

1、查询订单列表

2、根据用户id查询用户信息

实现思路:

先去查询第一个mapper方法,获取订单信息列表

在程序中(service),按需去调用第二个mapper方法去查询用户信息。

总之:

使用延迟加载方法,先去查询简单的sql最好单表,也可以关联查询),再去按需要加载关联查询的其它信息。

原文地址:https://www.cnblogs.com/kingxiaozi/p/6033800.html