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

发布时间:2023年12月23日

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>

在这里插入图片描述

<?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

<?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查询语句

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

在UserMapper.java中添加属性

User getUserById2(Integer id);

编写测试类

 @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、测试一对多的延迟加载,对比观察输出结果

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

 @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语句,如果不需要获得的信息则不会进行加载!

文章来源:https://blog.csdn.net/qq_62124267/article/details/135162596
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。