MyBatis 延迟加载:性能优化的秘密武器

引言

在 Java 开发中,MyBatis 作为一款优秀的持久层框架。在实际项目里,数据库查询性能是关键考量因素之一。而延迟加载--懒加载(Lazy Loading),作为提升性能的重要手段,能够避免不必要的数据查询,从而优化系统响应速度。那么,MyBatis 是否支持延迟加载呢?答案是肯定的。

什么是延迟加载

延迟加载,也被称为懒加载,是一种设计模式。在数据访问时,只有当真正需要用到某个数据时,才会去执行相应的数据库查询操作。这种方式能有效减少不必要的数据库交互,尤其是在处理关联对象时,避免一次性加载所有关联数据,从而提升系统性能。

举个例子,在一个博客系统中,一篇文章可能会关联多个评论。如果不使用延迟加载,在查询文章信息时,会同时把该文章下的所有评论都查询出来,即使这些评论可能暂时用不到。而使用延迟加载,只有当用户真正需要查看评论时,才会去查询数据库获取评论信息。

MyBatis 中的延迟加载支持

MyBatis 从设计之初就支持延迟加载,主要应用在关联查询(如 association 和 collection)中。下面从配置和使用两个方面详细介绍。

配置延迟加载

在 MyBatis 中,需要在配置文件里开启延迟加载功能。这里举例在spring boot当中使用,通过 @Configuration 类进行配置:

java 复制代码
import org.apache.ibatis.session.Configuration;
import org.mybatis.spring.boot.autoconfigure.ConfigurationCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MyBatisConfig {

    @Bean
    public ConfigurationCustomizer configurationCustomizer() {
        return new ConfigurationCustomizer() {
            @Override
            public void customize(Configuration configuration) {
                configuration.setLazyLoadingEnabled(true);
                configuration.setAggressiveLazyLoading(false);
            }
        };
    }
}

使用延迟加载

在映射文件中,使用 association 和 collection 标签时,可以通过 fetchType 属性指定加载方式。

association 延迟加载示例

假设存在用户(User)和部门(Department)两个实体,一个用户属于一个部门。

xml 复制代码
<resultMap id="UserResultMap" type="com.example.entity.User">
    <id property="id" column="id"/>
    <result property="name" column="name"/>
    <association property="department" javaType="com.example.entity.Department" 
                 select="com.example.mapper.DepartmentMapper.selectDepartmentById" 
                 column="department_id" fetchType="lazy"/>
</resultMap>

<select id="selectUserById" resultMap="UserResultMap">
    SELECT * FROM user WHERE id = #{id}
</select>

在上述示例中,fetchType="lazy" 表示使用延迟加载。只有当调用 User 对象的 getDepartment() 方法时,才会执行 DepartmentMapper 中的 selectDepartmentById 方法去查询部门信息。

collection 延迟加载示例

假设一个用户可以有多个订单(Order)。

xml 复制代码
<resultMap id="UserResultMapWithOrders" type="com.example.entity.User">
    <id property="id" column="id"/>
    <result property="name" column="name"/>
    <collection property="orders" ofType="com.example.entity.Order" 
                select="com.example.mapper.OrderMapper.selectOrdersByUserId" 
                column="id" fetchType="lazy"/>
</resultMap>

<select id="selectUserWithOrdersById" resultMap="UserResultMapWithOrders">
    SELECT * FROM user WHERE id = #{id}
</select>

这里同样使用 fetchType="lazy",只有在调用 User 对象的 getOrders() 方法时,才会执行 OrderMapper 中的 selectOrdersByUserId 方法查询订单信息。

总结

MyBatis 支持延迟加载,并且提供了灵活的配置和使用方式。合理运用延迟加载,可以有效减少数据库查询次数,提升系统性能.但是 需要必须要注意会话生命周期、性能平衡和序列化等问题。 需要根据业务需求和性能测试结果,合理选择是否使用延迟加载。

相关推荐
余槐i1 小时前
PostgreSQL 函数索引报错 must be immutable:3种绕法与代价
数据库·后端·sql·postgresql·性能优化
需要8262 小时前
Spring Bean 生命周期:从实例化到销毁的完整钩子
java·后端·spring
凤山老林3 小时前
Spring Boot 接入国密 SM2/SM3/SM4 的一些实践记录
spring boot·后端·python
伯恩bourne4 小时前
Spring Boot Bean 注册的两种方式:@Component 家族 vs @Configuration + @Bean
java·spring boot·后端
张彦峰ZYF4 小时前
停顿短不等于延迟低:G1、ZGC 与低延迟服务的目标分野、代价账本与选型标定
后端·回收暂停、应用停止总时长·到达安全点、分配停滞·屏障吃吞吐、并发线程吃核心·并发窗口吃堆余量·分区式靠挑回收集兑现目标·染色指针式不支持压缩引用
pride.li4 小时前
第03章 Python 教程-基础语法:注释与变量
服务器·前端·后端·python·算法·计算机视觉
upala5 小时前
【仓颉语言入门 · 第二篇 第 6 课】
后端
罗丹丹Luna5 小时前
移动端显示“已提交”以后:SAP 与低代码集成该怎样暴露真实状态
后端·架构
码事漫谈5 小时前
因为太想讨好你,所以AI会骗你
后端
吴凡wudianmei5 小时前
每调一次模型都花钱?如何用工程手段把调用压到最少?
前端·后端·架构