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

相关推荐
疾风sxp2 分钟前
nl2sql技术实现自动sql生成之langchain4j SqlDatabaseContentRetriever
java·人工智能·langchain4j
一勺菠萝丶33 分钟前
PDF24 转图片出现“中间横线”的根本原因与终极解决方案(DPI 原理详解)
java
姓蔡小朋友37 分钟前
Unsafe类
java
一只专注api接口开发的技术猿1 小时前
如何处理淘宝 API 的请求限流与数据缓存策略
java·大数据·开发语言·数据库·spring
荒诞硬汉1 小时前
对象数组.
java·数据结构
期待のcode1 小时前
Java虚拟机的非堆内存
java·开发语言·jvm
黎雁·泠崖1 小时前
Java入门篇之吃透基础语法(二):变量全解析(进制+数据类型+键盘录入)
java·开发语言·intellij-idea·intellij idea
仙俊红1 小时前
LeetCode484周赛T4
java
计算机毕设指导61 小时前
基于微信小程序的丽江市旅游分享系统【源码文末联系】
java·spring boot·微信小程序·小程序·tomcat·maven·旅游