MyBatis中延迟加载,全局和局部的开启使用与关闭

文章目录

MyBatis中延迟加载,全局和局部的开启使用与关闭

1、问题提出

在之前的文章一对多中,当我们有一个用户,他又一百个账户。

(1)在查询用户时,要不要把关联的账户信息查询出来?

(2)在查询账户时,要不要把关联的用户信息查询出来?

对于第一个问题,我们应该是什么时候需要查询账户信息,才查询。没必要每次查询用户信息都把账户信息也查询出来。因为如果每次都查询出账户信息,对我们的内存开销是很大的,而且每次查询也都不一定用到账户信息。

对于第二个问题,我们就可以在查询账户信息的时候查询出关联的用户信息,因为我们如果只是单纯的账户信息没有说明用户是谁,这对于我们来说是不友好的。也没什么意义,所以在每次查询账户信息的时候都要显示出关联的用户信息。

2、延迟加载和立即加载

第一个问题其实就是延迟加载。

第二个问题就是立即加载。

延迟加载

在真正的使用数据时才发起查询,不用的时候不查。按需加载(懒加载)。

立即加载

不管用不用,只要一调用方法,马上发起查询。

3、三种对应的表关系中的加载

四种表 关系:一对一,一对多,多对多。

一对多、多对多:通常情况下,我们都是采用延迟加载。

多对一、一对一:通常情况下,我们都是采用立即加载。

4、打开全局延迟加载(实现一对一的延迟加载)

这里的项目结构和mybatis关联查询里面的大部分内容是一样的,我们只需要更改一些配置信息。

更改mybatis-config.xml 中的信息

在这里添加两条setting标签配置信息。根据mybatis的文档

需要设置这两个属性。才能开启延迟加载。

  <settings>
	<!-- 打开全局延迟加载的开关 -->
	<setting name="lazyLoadingEnabled" value="true"/>
	<setting name="aggressiveLazyLoading" value="false"/>
</settings>
java 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>

    <!-- 配置延迟加载策略 -->
  	<settings>
    	<!-- 打开全局延迟加载的开关 -->
    	<setting name="lazyLoadingEnabled" value="true"/>
    	<setting name="aggressiveLazyLoading" value="false"/>
    </settings>

    <typeAliases>
        <package name="cn.fpl1116.pojo"/>
    </typeAliases>
    <!--使用dev环境-->
    <environments default="dev">
        <environment id="dev">
            <!--事务-->
            <transactionManager type="JDBC"></transactionManager>
            <!--
                type="POOLED":连接池
            -->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://127.0.0.1:3306/mybatis?characterEncoding=UTF-8"/>
                <property name="username" value="root"/>
                <property name="password" value=""/>
            </dataSource>
        </environment>
    </environments>
    <!--加载mapper映射文件-->
    <mappers>
        <package name="cn.fpl1116.mapper"/>
    </mappers>
</configuration>

5、实现一对多的延迟加载(将上面设置的全局延迟加载给注释掉)

编写UserMapper.xml

java 复制代码
<?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="cn.fpl1116.mapper.UserMapper">

    <resultMap id="getUserById2Result" type="cn.fpl1116.pojo.User">
        <id column="id" property="id"></id>
        <result column="username" property="username"/>
        <result column="address" property="address"/>
        <result column="sex" property="sex"/>
        <result column="birthday" property="birthday"/>

        <!--延迟加载的一对多-->
        <!--
            property="accountList":属性名
            ofType="com.by.pojo.Account":集合的泛型,等价于resultType
            select="com.by.mapper.AccountMapper.selectAccountByUid":要调用的select标签的id
            column="id":传递给select查询的参数
            fetchType="lazy":局部开启懒加载
        -->
        <collection property="accountList"
                    ofType="cn.fpl1116.pojo.Account"
                    select="cn.fpl1116.mapper.AccountMapper.selectAccountByUid"
                    column="id"
                    fetchType="lazy">
        </collection>
    </resultMap>
    <select id="getUserById2" parameterType="int" resultMap="getUserById2Result">
        <!-- SELECT u.*, a.id aid, a.uid uid, a.money money FROM user u LEFT JOIN account a ON u.id=a.uid WHERE u.id=#{id}-->
        select * from user where id=#{id}
    </select>
</mapper>

在UserMapper.xml中添加select查询语句

java 复制代码
<select id="selectAccountByUid" parameterType="int" resultType="cn.fpl1116.pojo.Account">
        SELECT * FROM account WHERE uid=#{uid}
    </select>

在UserMapper.java中添加属性

java 复制代码
User getUserById2(Integer id);

编写测试类

java 复制代码
 @Test
    public void testGetUserById2(){
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        User user = userMapper.getUserById2(41);
        System.out.println(user.getUsername());
        List<Account> accountList = user.getAccountList();
        for (Account account : accountList) {
            System.out.println(account);
        }
    }

延迟加载运行结果如下:

6、测试一对多的延迟加载,对比观察输出结果

将测试类中的另一个想要获得的信息给注释掉,如下:

java 复制代码
 @Test
    public void testGetUserById2(){
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        User user = userMapper.getUserById2(41);
        System.out.println(user.getUsername());
         //List<Account> accountList = user.getAccountList();
        //for (Account account : accountList) {
        //    System.out.println(account);
        //}
    }

运行结果如下:

结论:对比两种运行结果可以得到,延迟加载的使用意义:需要获得什么信息再去执行相应的sql语句,如果不需要获得的信息则不会进行加载!

相关推荐
陌上花开࿈2 小时前
调用第三方接口
java
Aileen_0v02 小时前
【玩转OCR | 腾讯云智能结构化OCR在图像增强与发票识别中的应用实践】
android·java·人工智能·云计算·ocr·腾讯云·玩转腾讯云ocr
桂月二二4 小时前
Java与容器化:如何使用Docker和Kubernetes优化Java应用的部署
java·docker·kubernetes
liuxin334455664 小时前
学籍管理系统:实现教育管理现代化
java·开发语言·前端·数据库·安全
小马爱打代码4 小时前
设计模式详解(建造者模式)
java·设计模式·建造者模式
栗子~~5 小时前
idea 8年使用整理
java·ide·intellij-idea
2301_801483695 小时前
Maven核心概念
java·maven
Q_19284999065 小时前
基于Spring Boot的电影售票系统
java·spring boot·后端
我要学编程(ಥ_ಥ)6 小时前
初始JavaEE篇 —— 网络原理---传输层协议:深入理解UDP/TCP
java·网络·tcp/ip·udp·java-ee
就爱学编程6 小时前
重生之我在异世界学编程之C语言:数据在内存中的存储篇(下)
java·服务器·c语言