欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

(十一)延迟加载

程序员文章站 2024-03-26 14:12:41
...

目录


延迟加载的含义

    比如现在我们有一个网页,在网页上显示 订单信息,然后鼠标某一个 订单信息 ,则会显示产生这个订单的 用户信息

     我们可以看出,当用户不点击具体的 订单信息 的时候,我们是不需要去显示具体的 用户信息 的 ;也就是说,开始我们只需要查询 订单表,即可完成需求,等到需要显示用户信息了,再去查询 用户表 ,这种 按需加载,也就是 延迟加载


延迟加载的意义

我们都知道数据库在进行 关联查询 的时候,关联的表越多,查询速度越慢 ;

比如上面的情况,不使用延迟加载,则开始就是有关联查询,查询出所有信息;

而我们使用延迟加载,就会 按需加载,首先只会去查询需要的表,比 关联查询,将要快许多。

并且有些时候,并不是每个定单用户都会点击查看的,因此实质,也不需要查询所有的信息出来,按需查询 是个极好的选择

因此,延迟加载,会大大的提高数据库的性能 ;


mybatis支持延迟加载

使用 resultMapassociationcollection 标签都支持实现延迟加载 ;


使用方法

需求:查询订单及其关联的用户信息 ;

由于我们使用 懒惰加载因此,我们需要配置 2 个 statement 对象,一个用于 直接查询,一个 用于 按需查询

  1. 配置 直接查询sql

    查询订单表

    <select id="findOrdersAndUserLazyLoading" resultMap="findOrdersAndUserLazyLoadingMap" >
        SELECT * FROM `order`
    </select>
  2. 配置 懒加载 使用的 sql

    查询用户表

    <select id="findUserById" parameterType="int" resultType="xin.ijava.pojo.User">
       select * from User where id = #{id}
    </select>
  3. 创建 resultMap 实现懒加载

    使用 selectcolumn 实现懒加载 ;

    <!--懒加载-->
    <resultMap id="findOrdersAndUserLazyLoadingMap" type="xin.ijava.pojo.OrdersUsers">
        <id column="order_id" property="order_id"/>
        <result column="user_id" property="user_id"/>
        <result column="create_time" property="createTime"/>
    
        <!--懒加载用户信息-->
        <!--select  : 指定懒加载执行的 sql -->
        <!--column  :指定懒加载,关联查询的列 -->
        <association property="user" javaType="xin.ijava.pojo.User" select="xin.ijava.dao.UserMapper.findUserById" column="user_id">
            <id column="id" property="id"/>
            <result column="name" property="name"/>
            <result column="sex" property="sex"/>
            <result column="address" property="address"/>
        </association>
    
    </resultMap>
  4. 编写接口

    public List<OrdersUsers> findOrdersAndUserLazyLoading() throws Exception ;
  5. 测试代码

    @Test
    public void test3() throws Exception {
        SqlSession sqlSession = factory.openSession();
    //        获取代理对象,参数写上类的全路径名
        UserCustomerMapper userMapper = sqlSession.getMapper(xin.ijava.dao.UserCustomerMapper.class);
    //         利用代理对象,操作
        List<OrdersUsers> users = userMapper.findOrdersAndUserLazyLoading();
    
        for (OrdersUsers ordersUsers :
                users) {
            System.out.println(ordersUsers);
        }
    //        System.out.println(users);
    }
  6. 观察 log

    [service] 2018-09-11 15:35:37,895 - xin.ijava.dao.UserCustomerMapper.findOrdersAndUserLazyLoading -8274 [main] DEBUG xin.ijava.dao.UserCustomerMapper.findOrdersAndUserLazyLoading  - ==>  Preparing: SELECT * FROM `order` 
    [service] 2018-09-11 15:35:38,797 - xin.ijava.dao.UserCustomerMapper.findOrdersAndUserLazyLoading -9176 [main] DEBUG xin.ijava.dao.UserCustomerMapper.findOrdersAndUserLazyLoading  - ==> Parameters: 
    [service] 2018-09-11 15:35:39,917 - xin.ijava.dao.UserCustomerMapper.findOrdersAndUserLazyLoading -10296 [main] DEBUG xin.ijava.dao.UserCustomerMapper.findOrdersAndUserLazyLoading  - <==      Total: 4
    [service] 2018-09-11 15:36:06,088 - xin.ijava.dao.UserMapper.findUserById -36467 [main] DEBUG xin.ijava.dao.UserMapper.findUserById  - ==>  Preparing: select * from User where id = ? 
    [service] 2018-09-11 15:36:06,089 - xin.ijava.dao.UserMapper.findUserById -36468 [main] DEBUG xin.ijava.dao.UserMapper.findUserById  - ==> Parameters: 5(Integer)
    [service] 2018-09-11 15:36:06,098 - xin.ijava.dao.UserMapper.findUserById -36477 [main] DEBUG xin.ijava.dao.UserMapper.findUserById  - <==      Total: 1
    xin.ijava.pojo.OrdersUsers_$$_jvstbd2_0@692ec5f8
    [service] 2018-09-11 15:36:15,714 - xin.ijava.dao.UserMapper.findUserById -46093 [main] DEBUG xin.ijava.dao.UserMapper.findUserById  - ==>  Preparing: select * from User where id = ? 
    [service] 2018-09-11 15:36:15,716 - xin.ijava.dao.UserMapper.findUserById -46095 [main] DEBUG xin.ijava.dao.UserMapper.findUserById  - ==> Parameters: 1(Integer)
    [service] 2018-09-11 15:36:15,719 - xin.ijava.dao.UserMapper.findUserById -46098 [main] DEBUG xin.ijava.dao.UserMapper.findUserById  - <==      Total: 1
      xin.ijava.pojo.OrdersUsers_$$_jvstbd2_0@63c1edd9
    [service] 2018-09-11 15:36:20,415 - xin.ijava.dao.UserMapper.findUserById -50794 [main] DEBUG xin.ijava.dao.UserMapper.findUserById  - ==>  Preparing: select * from User where id = ? 
    [service] 2018-09-11 15:36:20,416 - xin.ijava.dao.UserMapper.findUserById -50795 [main] DEBUG xin.ijava.dao.UserMapper.findUserById  - ==> Parameters: 4(Integer)
    [service] 2018-09-11 15:36:20,419 - xin.ijava.dao.UserMapper.findUserById -50798 [main] DEBUG xin.ijava.dao.UserMapper.findUserById  - <==      Total: 1
    xin.ijava.pojo.OrdersUsers_$$_jvstbd2_0@7608443a
    xin.ijava.pojo.OrdersUsers_$$_jvstbd2_0@29efafae

    我在遍历的时候,下了断点 ;可以看见,在我们访问用户信息之前,是没有执行查询 user 表的;

    在遍历的时候,才开始需要谁,就去查找谁 ;并且我们发现 4 个订单,只执行了 3sql,这是因为其中一级缓存的原因 ;


假如 mybatis 不支持延迟加载

假如mybatis 不支持 延迟加载 ,我们也不要慌(问题很大,慌也没有用),它不支持,离开它,我们还不能做事了啊。想一下,我们还有许多其他持久层的框架使用啊 ;

说正事,假如 mybatis 不支持 延迟加载 ,我们也是可以手动实现的;

我们定义 2 个方法,分别用于 直接查询按需查询 ;在页面上先使用 直接查询 查询我们需要的订单信息,然后如果需要继续查询关联的用户信息,则在 services 层 拦截一下,传入产生订单的用户 id,然后调用 按需查询 方法 ;

一样可以完成 延迟加载

相关标签: 延迟加载