zoukankan      html  css  js  c++  java
  • Mybatis学习系列(六)延迟加载

    延迟加载其实就是将数据加载时机推迟,比如推迟嵌套查询的执行时机。在Mybatis中经常用到关联查询,但是并不是任何时候都需要立即返回关联查询结果。比如查询订单信息,并不一定需要及时返回订单对应的产品信息,查询商品分类信息并不一定要及时返回该类别下有哪些产品,这种情况一下需要一种机制,当需要查看时,再执行查询,返回需要的结果集,这种需求在Mybatis中可以使用延迟加载机制来实现。延迟加载可以实现先查询主表,按需实时做关联查询,返回关联表结果集,一定程度上提高了效率。

    Mapper.xml映射文件

    以商品类别category和商品product为例,一个类别下可以有多个商品,一个商品属于一种类别。

    编写lazyLoadMapper.xml映射文件

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE mapper 
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.sl.mapper.LazyLoadMapper">
            <!-- 分类信息查询 -->
            <select id="lazyLoadTest"  resultMap="lazyLoadProductsByCategoryTest">
                select * from category where id=#{id}
            </select>
            <resultMap id="lazyLoadProductsByCategoryTest" type="com.sl.po.Category">
                <id column="id" property="Id"></id>
                <result column="name" property="Name"></result>
                <result column="remark" property="Remark"></result>
                <!-- 一个分类对应多个产品,此处使用collection -->
                <collection property="productList" ofType="com.sl.po.Product"  column="id" select="selectProductsByCategoryId"></collection>
            </resultMap>
            
            <!-- 嵌套查询返回商品信息,延迟加载将要执行的sql -->
            <select id="selectProductsByCategoryId"  resultType="com.sl.po.Product">
                select * from products where categoryid=#{id} 
            </select>
            
    </mapper>

    启用延迟加载和按需加载

    Mybatis配置文件中通过两个属性lazyLoadingEnabled和aggressiveLazyLoading来控制延迟加载和按需加载。

    lazyLoadingEnabled:是否启用延迟加载,mybatis默认为false,不启用延迟加载。lazyLoadingEnabled属性控制全局是否使用延迟加载,特殊关联关系也可以通过嵌套查询中fetchType属性单独配置(fetchType属性值lazy或者eager)。

    aggressiveLazyLoading:是否按需加载属性,默认值false,lazyLoadingEnabled属性启用时只要加载对象,就会加载该对象的所有属性;关闭该属性则会按需加载,即使用到某关联属性时,实时执行嵌套查询加载该属性。

    SqlMapConfig.xml中修改配置,注册lazyLoadMapper.xml

    <settings>
        <!-- 启用延迟加载特性,不配置默认关闭该特性-->
        <setting name="lazyLoadingEnabled" value="true"></setting>
        <!-- 按需加载: false:使用关联属性,及时加载;    true,加载对象,则加载所有属性, -->
         <setting name="aggressiveLazyLoading" value="false"/>
        </settings>
    
    <mappers>
            <!-- 注册Mapper.xml文件 -->
            <mapper resource="mapper/lazyLoadMapper.xml"></mapper>        
    </mappers>

    运行测试

    添加mapper接口

    package com.sl.mapper;
    
    import java.util.List;
    
    import com.sl.po.Category;
    import com.sl.po.Product;
    
    public interface LazyLoadMapper {
        
        
        Category lazyLoadTest(int id);
    
        //嵌套查询
        List<Product> selectProductsByCategoryId(int cId);
    }
    View Code

    测试方法

    package com.sl.test;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.math.BigDecimal;
    import java.text.DateFormat;
    import java.text.ParseException;
    import java.text.SimpleDateFormat;
    
    import org.apache.ibatis.io.Resources;
    import org.apache.ibatis.session.SqlSession;
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.apache.ibatis.session.SqlSessionFactoryBuilder;
    import org.junit.Before;
    import org.junit.Test;
    
    import com.sl.mapper.LazyLoadMapper;
    import com.sl.mapper.ProductMapper;
    import com.sl.mapper.UnitMapper;
    import com.sl.po.Category;
    import com.sl.po.Product;
    import com.sl.po.ProductDetailInfo;
    import com.sl.po.ProductInfo;
    import com.sl.po.ProductVo;
    import com.sl.po.User;
    
    import java.util.ArrayList;
    import java.util.Date;
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.List;
    import java.util.Map;
    
    public class TestLazyLoadMapperClient {
    
        // 定义会话SqlSession
        SqlSession session = null;
    
        @Before
        public void init() throws IOException {
            // 定义mabatis全局配置文件
            String resource = "SqlMapConfig.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
            SqlSessionFactory factory = builder.build(inputStream);
            // 根据sqlSessionFactory产生会话sqlsession
            session = factory.openSession();
        }
    
        // 延迟加载
        @Test
        public void testoneToManyTestCollectionSelect() {
    
            LazyLoadMapper mapper = session.getMapper(LazyLoadMapper.class);
    
            Category category = mapper.lazyLoadTest(1);
    
            //System.out.println(category);
            System.out.println(category.getName());
    
            if (category.getProductList().size() > 0) {
                for (Product pro : category.getProductList()) {
                    System.out.println(pro);
                }
            }
            // 关闭会话
            session.close();
        }
    
    }
    View Code

    运行程序查看sql执行记录:

    当前配置:启用延迟加载lazyLoadingEnabled=true和按需加载aggressiveLazyLoading=false

    Step1: 执行Mapper方法lazyLoadTest,实际只执行了select * from category where id=#{id}

    Step2: 执行System.out.println(category.getName()),加载属性,由于启用按需加载aggressiveLazyLoading=false,name属性此前已加载好,所以此处无数据库交互

    Step3: 执行category.getProductList().size(),加载属性productList,按需加载需要执行延迟加载sql脚本select * from products where categoryid=#{id},与数据库交互

    将aggressiveLazyLoading属性设为为true,即:

    <setting name="aggressiveLazyLoading" value="false"/>

    再一下执行过程:

    此时的配置:启用延迟加载lazyLoadingEnabled=true和关闭按需加载aggressiveLazyLoading=true(即加载对象则加载所有属性)

    Step1: 执行Mapper方法lazyLoadTest,实际只执行了select * from category where id=#{id}

    Step2: 执行System.out.println(category.getName()),访问name属性,由于启用按需加载aggressiveLazyLoading=true,关闭按需加载,则加载category对象时加载该对象的所有属性,执行延迟加载sql脚本select * from products where categoryid=#{id},与数据库交互

    Step3: 执行category.getProductList().size(),访问productList属性,该 性step2已加载好,此处无需数据库交互

    对比上下两个step2可以发现 aggressiveLazyLoading=true /false的区别。

  • 相关阅读:
    图片垂直居中的方法(适合只有一行文字和图片)
    微信小程序 this.setData() 详解
    phpstorm 2017激活码(方法)
    WebSocket 协议 详解
    容器装不下内容时,显示滚动条
    Restore IP Addresses
    Reverse Linked List II
    Subsets II
    Decode Ways
    Gray Code
  • 原文地址:https://www.cnblogs.com/ashleyboy/p/9286814.html
Copyright © 2011-2022 走看看