Mybatis延迟加载的实现示例

 更新时间:2026年04月02日 10:03:23   作者:小王不爱笑132  
延迟加载是 MyBatis 的一种优化机制,也称为懒加载,本文就来详细的介绍一下Mybatis延迟加载的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

什么是延迟加载

延迟加载(Lazy Loading)是 MyBatis 的一种优化机制,也称为懒加载。它指的是在进行关联查询时,按需加载数据,而不是一次性加载所有关联数据,从而提高系统性能,减少不必要的数据库查询。

延迟加载配置

全局配置(SqlMapConfig.xml)

需要在 MyBatis 核心配置文件中开启延迟加载开关:

<settings>
    <!-- 开启延迟加载 -->
    <setting name="lazyLoadingEnabled" value="true"/>
    <!-- 将积极加载改为消极加载(按需加载) -->
    <setting name="aggressiveLazyLoading" value="false"/>
</settings>
  • lazyLoadingEnabled:全局开启延迟加载开关(默认 false)
  • aggressiveLazyLoading:是否开启积极加载(默认 false)
    • 积极加载:加载一个对象时,会同时加载所有关联对象
    • 消极加载:只有真正使用关联对象时才会加载

延迟加载实现(以 Account 和 User 为例)

1. 实体类定义

Account 类(包含 User 关联对象):

public class Account implements Serializable {
    private Integer id;
    private Integer uid;
    private Double money;
    // 关联的用户对象
    private User user;
    // getter/setter/toString省略
}

User 类:

public class User implements Serializable {
    private Integer id;
    private String name;
    private Date birthday;
    private String sex;
    private String address;
    // getter/setter/toString省略
}

2. Mapper 接口定义

AccountMapper 接口:

public interface AccountMapper {
    // 查询所有账户
    List<Account> findAll();
}

UserMapper 接口:

public interface UserMapper {
    // 根据ID查询用户
    User findById(Integer id);
}

3. Mapper 映射文件配置(关键)

AccountMapper.xml 中配置延迟加载:

<mapper namespace="com.qcby.mapper.AccountMapper">
    <!-- 延迟加载配置 -->
    <select id="findAll" resultMap="accountMap">
        select * from account
    </select>
    <resultMap id="accountMap" type="Account">
        <id column="id" property="id"/>
        <result column="uid" property="uid"/>
        <result column="money" property="money"/>
        <!-- 配置延迟加载 -->
        <association 
            property="user"        <!-- 关联对象在Account中的属性名 -->
            javaType="User"        <!-- 关联对象的类型 -->
            select="com.qcby.mapper.UserMapper.findById"  <!-- 延迟加载时执行的查询 -->
            column="uid"/>         <!-- 传递给select查询的参数(账户表中的uid字段) -->
    </resultMap>
</mapper>

UserMapper.xml 中需要有对应的查询方法:

<mapper namespace="com.qcby.mapper.UserMapper">
    <select id="findById" parameterType="int" resultType="User">
        select * from user where id = #{id}
    </select>
</mapper>

延迟加载测试代码

public class Test02 {
    private InputStream in;
    private SqlSession session;
    private AccountMapper mapper;
    @Before
    public void init() throws Exception {
        // 加载配置文件
        in = Resources.getResourceAsStream("SqlMapConfig.xml");
        // 创建工厂对象
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
        // 创建session对象
        session = factory.openSession();
        // 获取代理对象
        mapper = session.getMapper(AccountMapper.class);
    }
    @After
    public void destroy() throws Exception {
        session.close();
        in.close();
    }
    @Test
    public void testLazyLoading() {
        // 1. 查询所有账户(此时只会执行account表的查询)
        List<Account> accounts = mapper.findAll();
        // 2. 遍历账户列表
        for (Account account : accounts) {
            System.out.println("账户信息:" + account.getMoney());
            // 3. 当需要使用user属性时,才会执行user表的查询(延迟加载触发点)
            System.out.println("用户信息:" + account.getUser().getName());
        }
    }
}

延迟加载执行流程解析

  1. 执行mapper.findAll()时,MyBatis 只查询 account 表,获取账户基本信息
  2. 此时 account 对象中的 user 属性为代理对象(尚未查询数据库)
  3. 当执行account.getUser().getName()时,才会触发 User 查询
  4. 执行com.qcby.mapper.UserMapper.findById方法,传入 uid 参数
  5. 获取用户信息并赋值给 account 的 user 属性

延迟加载的优点

  1. 减少不必要的 SQL 查询,提高数据库性能
  2. 减少内存占用,只加载当前需要的数据
  3. 适用于关联数据较多但不一定都会使用的场景

注意事项

  1. 延迟加载只对关联查询有效(一对一、一对多等)
  2. 必须在核心配置文件中开启延迟加载开关
  3. 如果提前关闭 SqlSession,会导致延迟加载失败(无法执行后续查询)
  4. 延迟加载通过 CGLIB 或 JDK 动态代理实现,关联对象是代理对象

到此这篇关于Mybatis延迟加载的实现示例的文章就介绍到这了,更多相关Mybatis延迟加载内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • java扩展Hibernate注解支持java8新时间类型

    java扩展Hibernate注解支持java8新时间类型

    这篇文章主要介绍了java扩展Hibernate注解支持java8新时间类型,需要的朋友可以参考下
    2014-04-04
  • Java设计模式之备忘录模式

    Java设计模式之备忘录模式

    这篇文章主要介绍了Java设计模式之备忘录模式,备忘录模式(Memento Pattern),属于行为型设计模式,目的是用于保存一个对象在某一时刻的状态,以便于在将来某个时刻根据此状态恢复该对象,需要的朋友可以参考下
    2023-12-12
  • java接口防重提交的处理方法

    java接口防重提交的处理方法

    本文主要介绍了java接口防重提交的处理方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-05-05
  • jpa使用manyToOne(opntional=true)踩过的坑及解决

    jpa使用manyToOne(opntional=true)踩过的坑及解决

    这篇文章主要介绍了jpa使用manyToOne(opntional=true)踩过的坑及解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-10-10
  • java解析JT808协议的实现代码

    java解析JT808协议的实现代码

    这篇文章主要介绍了java解析JT808协议的实现代码,需要的朋友可以参考下
    2020-03-03
  • Java判断两个日期相差天数的方法

    Java判断两个日期相差天数的方法

    这篇文章主要介绍了Java判断两个日期相差天数的方法,以实例形式对比分析了java进行日期换算及对比的相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-10-10
  • SpringBoot数据层测试事务回滚的实现流程

    SpringBoot数据层测试事务回滚的实现流程

    这篇文章主要介绍了SpringBoot数据层测试事务回滚的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习吧
    2022-10-10
  • Spring注解驱动之关于@Bean注解指定初始化和销毁的方法

    Spring注解驱动之关于@Bean注解指定初始化和销毁的方法

    这篇文章主要介绍了Spring注解驱动之关于@Bean注解指定初始化和销毁的方法,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-09-09
  • Java匿名内部类的使用方法举例详解

    Java匿名内部类的使用方法举例详解

    Java中的匿名内部类是一种没有名字的局部内部类,主要用于一次性实现接口或继承类的场合,它们常见于GUI事件处理、多线程编程等场景,简化代码结构同时提高开发效率,需要的朋友可以参考下
    2024-09-09
  • 集群环境中使用ehcache_动力节点Java学院整理

    集群环境中使用ehcache_动力节点Java学院整理

    这篇文章主要为大家详细介绍了集群环境中使用ehcache的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-08-08

最新评论