IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> mybatis——轻松使用lazyLoadingEnabled(懒加载)和aggressiveLazyLoading解决mybatis中的“N+1”问题(超详细) -> 正文阅读

[Java知识库]mybatis——轻松使用lazyLoadingEnabled(懒加载)和aggressiveLazyLoading解决mybatis中的“N+1”问题(超详细)

目录

1.代码演示

1.1创建POJO

1.2创建Mapper接口

1.3创建XML映射文件

1.4创建mybatis-config.xml文件

1.5测试未使用lazyLoadingEnabled和aggressiveLazyLoading

2.lazyLoadingEnabled和aggressiveLazyLoading

2.1配置lazyLoadingEnabled并测试

?2.2配置aggressiveLazyLoading并测试


什么是N+1:

例如我们有用户User和订单Order两张表,在一般情况下我们只需要查询用户就可以,(这就是所谓的“1”)但是User和Order都被查询出来了,每一个用户User都对应一个或者多个订单Order,查询出来的Order订单就是所谓的“N”。或许叫“1+N”会更贴切,但是这样的查询就会造成不必要的性能浪费。

1.代码演示

1.1创建POJO

我们有User和Order两个对象

package user.pojo;

import lombok.Data;
@Data
public class User {
    private long id;
    private String userName;
    private int userAge;
    private Order orderId;
}
package user.pojo;

import lombok.Data;

@Data
public class Order {
    private long id;
    private String orderName;
    private String note;
}

1.2创建Mapper接口

package user.mapper;

import user.pojo.User;

public interface UserMapper {
    User getUser(long id);
}
package user.mapper;

import user.pojo.Order;

public interface OrderMapper {
    Order getOrder(long id);
}

1.3创建XML映射文件

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="user.mapper.UserMapper">
    <resultMap id="UserMap" type="user.pojo.User">
        <id property="id" column="id"/>
        <result property="userName" column="userName"/>
        <result property="userAge" column="userAge"/>
        <association property="orderId" column="id" select="user.mapper.OrderMapper.getOrder"/>
    </resultMap>
    <select id="getUser" resultMap="UserMap">
        select * from user_user where id=#{id}
    </select>
</mapper>

?注意UserMapper.xml中的?<association property="orderId" column="id" select="user.mapper.OrderMapper.getOrder"/>的级联

<?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="user.mapper.OrderMapper">
    <select id="getOrder" resultType="user.pojo.Order">
        select * from order_order where id=#{id}
    </select>
</mapper>

1.4创建mybatis-config.xml文件

<?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>
    <properties resource="jdbc.properties" />
    <settings>
        <setting name="logImpl" value="LOG4J" />
    </settings>
    <typeAliases>
        <package name="user.pojo" />
    </typeAliases>
    <!-- 数据库环境 -->
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC" />
            <dataSource type="POOLED">
                <property name="driver" value="${database.driver}" />
                <property name="url" value="${database.url}" />
                <property name="username" value="${database.username}" />
                <property name="password" value="${database.password}" />
            </dataSource>
        </environment>
    </environments>
    <mappers>
      <package name="user.mapper"/>
    </mappers>
</configuration>

1.5测试未使用lazyLoadingEnabled和aggressiveLazyLoading

package user.main;

import lombok.extern.log4j.Log4j;
import org.apache.ibatis.session.SqlSession;
import user.mapper.UserMapper;
import user.pojo.User;
import user.utils.SqlSessionFactoryUtils;
@Log4j
public class UserTest {
    public static void main(String[] args) {

        SqlSession sqlSession=SqlSessionFactoryUtils.openSqlSession();
        UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
        User user =userMapper.getUser(1l);
        log.info(user.getUserName());
    }
}

主要看日志执行了几条sql

?这是代码演示"N+1",下面我们使用lazyLoadingEnabled和aggressiveLazyLoading

2.lazyLoadingEnabled和aggressiveLazyLoading

lazyLoadingEnabled是全局延时设置,也叫懒加载,默认为false,所有的级联都会被加载出来,但是全部加载或者不加载就过于武断,达不到我们要的效果,所以就有了aggressiveLazyLoading

aggressiveLazyLoading的默认值在3.4.1之前包含当前版本为false,在3.4.1版本之后为true

值为false时,只加载调用的属性,不调用的不加载,例如:

在测试案例中,User调用了getUserName()这个属性,那么加载的只有User这个对象

如果值为true,只要调用User对象的任何一个方法就会加载整个对象(包含Order的查询)会造成级联

2.1配置lazyLoadingEnabled并测试

?在mybatis-config.xml文件中配置settings,<setting name="lazyLoadingEnabled" value="true"/>,
我用的是mybatis3.5.5的版本所以不用显示配置

再次运行上方的测试案例,结果如下,就只剩下了一个sql,因为全部延迟加载了

?2.2配置aggressiveLazyLoading并测试

如果将aggressiveLazyLoading的值设置为true

?并且再次运行测试案例

?结果如下

?你会发现明明User对象只调用getuserName()方法,但是也出现了Order的sql查询

如果看完还是不太理解,尽量动手尝试一下,lazyLoadingEnabled比较好理解,重点是aggressiveLazyLoading不太好理解

以上为个人理解,如有不对欢迎指出,

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-12-23 15:37:37  更:2021-12-23 15:38:26 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 7:20:39-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码