zoukankan      html  css  js  c++  java
  • mybatis_延迟加载

    延迟加载

    所谓的 mybatis 延迟加载,指的是当进行多个表之间的关联查询时,先从单表中进行查询,按照一定的设计规则,需要时再对该表所关联的表单继续进行查询

    好比如在某个购物网站上填写收货地址时,先加载省份,等用户选择了所在省份后,系统在关联加载处该省份下的城市

    延迟加载最主要的一个作用就是减小了数据库的压力

    三种不同的加载类型:

    1:直接加载:当对一个表执行 select 语句时,马上对该表所关联的表执行 select 语句(将该表与该表所关联的表的数据直接查询出来)

    2:侵入式延迟:当对一个表执行 select 语句时,不会对该表的关联表执行 select 查询,但当访问主加载对象的详情属性时,就会马上执行关联的select查询

    3:深度延迟:当对一个表执行 select 语句时,不会对该表的关联表执行 select 查询,访问主加载对象的详情也不会对该表的关联对象执行 select 查询,只有当真正访问关联对象详情时,才会执行对关联对象的 select 查询

    ## 未设置延迟加载时的情况

    1:创建mapper

    <?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.doaoao.dao.TeamDao">
    
        <!-- 根据teamid 查询team下的篮球队员 -->
        <select id="selectPlayerByTeamId" resultType="Player">
            select id,name from t_player where tid=#{id}
        </select>
    
        <!-- 关系属性映射关系 -->
        <!-- 集合的数据来自 select 查询,该查询的条件是 selectTeamByIdAlone 查出的id -->
        <resultMap id="teamMapAlone" type="Team">
            <id column="id" property="id"></id>
            <result column="name" property="name"></result>
    
            <collection property="playerList" ofType="Player" select="selectPlayerByTeamId" column="id"></collection>
        </resultMap>
    
        <select id="selectTeamByIdAlone" resultMap="teamMapAlone">
            SELECT id,name FROM t_team where id=#{id}
        </select>
    </mapper>

    2:创建接口

    package com.doaoao.dao;
    import com.doaoao.bean.Team;
    public interface TeamDao {
        Team selectTeamByIdAlone(int id);
    }

    3:创建测试类

        @Test
        public void selectTeamByIdAlone() {
            Team team = teamDao.selectTeamByIdAlone(2);
            System.out.println(team);
        }

    4:执行后的数据分析

    // 当未设置延迟加载时,查询主表后会查询该表所关联的表
    
    // 第一条SQL 语句,查询表 t_team
    [DEBUG][2019-04-16 15:19:25]==>  Preparing: SELECT id,name FROM t_team where id=? 
    [DEBUG][2019-04-16 15:19:25]==> Parameters: 2(Integer)
    [TRACE][2019-04-16 15:19:25]<==    Columns: id, name
    [TRACE][2019-04-16 15:19:25]<==        Row: 2, huren
    
    // 第二条 SQL 语句,查询表 t_player
    [DEBUG][2019-04-16 15:19:25]====>  Preparing: select id,name from t_player where tid=? 
    [DEBUG][2019-04-16 15:19:25]====> Parameters: 2(Integer)
    [TRACE][2019-04-16 15:19:25]<====    Columns: id, name
    [TRACE][2019-04-16 15:19:25]<====        Row: 2, kobe
    [DEBUG][2019-04-16 15:19:25]<====      Total: 1
    [DEBUG][2019-04-16 15:19:25]<==      Total: 1
    Team{id=2, name='huren'}

    ## 设置延迟加载模式

    在配置文件 mybatis.xml中(将下方的内容放在 properties和typeAliases之间)

        <!-- 设置延迟加载 -->
        <settings>
            <!-- 设置延迟加载的总开关 -->
            <setting name="lazyLoadingEnabled" value="true" />
    
            <!-- 侵入式延迟加载开关 -->
            <!-- 注意:3.4.1把那本之前value默认未true,之后版本默认未false -->
            <setting name="aggressiveLazyLoading" value="true" />
        </settings>

    执行后的结果分析

    // 只执行了一条 SQL 语句
    [DEBUG][2019-04-16 15:47:33]==>  Preparing: SELECT id,name FROM t_team where id=? 
    [DEBUG][2019-04-16 15:47:33]==> Parameters: 2(Integer)
    [TRACE][2019-04-16 15:47:33]<==    Columns: id, name
    [TRACE][2019-04-16 15:47:33]<==        Row: 2, huren
    [DEBUG][2019-04-16 15:47:33]<==      Total: 1

     # 当将测试方法修改未如下配置时,会分别执行两条 SQL 语句

    @Test
    public void selectTeamByIdAlone() {
        Team team = teamDao.selectTeamByIdAlone(1);
        System.out.println(team.getName());
    }

     ## 深度延迟加载

    将 lazyLoadingEnabled 打开,将 aggressiveLazyLoading 关闭即可。

        <!-- 设置延迟加载 -->
        <settings>
            <!-- 设置延迟加载的总开关 -->
            <setting name="lazyLoadingEnabled" value="true" />
    
            <!-- 侵入式延迟加载开关 -->
            <!-- 注意:3.4.1把那本之前value默认未true,之后版本默认未false -->
            <setting name="aggressiveLazyLoading" value="true" />
        </settings>

     当执行下方测试方法时,只执行一条SQL语句,因为没有使用到player相关数据

    @Test
    public void selectTeamByIdAlone() {
        Team team = teamDao.selectTeamByIdAlone(1);
        System.out.println(team.getName());
    }

     当执行下方测试方法时,执行两条SQL语句,因为使用到player相关数据

     @Test
    public void selectTeamByIdAlone() {
        Team team = teamDao.selectTeamByIdAlone(1);
    
        // 使用到 player 的数据
        System.out.println(team.getPlayerList().size());
    }

    ... 未完待续

    本笔记参考自:小猴子老师教程 http://www.monkey1024.com

  • 相关阅读:
    JDBC
    SQL语法(3)
    数据库设计和三大范式
    SQL语法(2)
    SQL语法(1)
    数据库的概念以及MYSQL的安装和卸载
    IO流(下)
    IO流(上)
    bash: javac: command not found...
    R语言绘制地图
  • 原文地址:https://www.cnblogs.com/Doaoao/p/10717704.html
Copyright © 2011-2022 走看看