Mybatis中的懒加载
目录
基本概念
懒加载的应用场景
如何配置懒加载
全局配置
局部配置
懒加载的工作原理
示例代码
一对一懒加载
一对多懒加载
懒加载的触发条件
懒加载的优缺点
优点:
缺点:
解决N + 1查询问题的方法
注意事项
示例
对应sql语句
当只需输出Tname时
当输出全部信息时
懒加载(Lazy Loading)是 MyBatis 提供的一种优化数据加载的策略,它可以在需要时才加载关联数据,而不是在查询主对象时就立即加载所有关联数据。
基本概念
懒加载也称为延迟加载,它的核心思想是:只有在真正需要使用关联数据时才会执行查询,这样可以减少不必要的数据库查询,提高系统性能。
懒加载的应用场景
- 一对一关联查询(<association>)
- 一对多关联查询(<collection>)
- 多对多关联查询
如何配置懒加载
全局配置
在Mybatis配置文件中启用懒加载:
<settings><!-- 启用懒加载 --><setting name="lazyLoadingEnabled" value="true"/><!-- 设置积极加载为false,按需加载 --><setting name="aggressiveLazyLoading" value="false"/>
</settings>
局部配置
在映射文件中为特定关联配置懒加载:
<association property="teacher" javaType="Teacher" column="t_id" select="getTeacher" fetchType="lazy"/> <!-- 显式指定懒加载 -->
懒加载的工作原理
- 当查询主对象时,Mybatis只执行主查询SQL
- 返回的代理对象中包含关联对象的引用
- 当代码第一次访问关联对象时,Mybatis才会执行关联查询SQL
- 查询结果被填充到关联对象中
示例代码
一对一懒加载
<resultMap id="studentMap" type="Student"><id property="id" column="id"/><result property="name" column="name"/><!-- 懒加载teacher --><association property="teacher" javaType="Teacher" column="teacher_id" select="getTeacherById" fetchType="lazy"/>
</resultMap><select id="getStudent" resultMap="studentMap">SELECT * FROM student WHERE id = #{id}
</select><select id="getTeacherById" resultType="Teacher">SELECT * FROM teacher WHERE id = #{teacher_id}
</select>
一对多懒加载
<resultMap id="teacherMap" type="Teacher"><id property="id" column="id"/><result property="name" column="name"/><!-- 懒加载students --><collection property="students" ofType="Student" column="id" select="getStudentsByTeacherId" fetchType="lazy"/>
</resultMap><select id="getTeacher" resultMap="teacherMap">SELECT * FROM teacher WHERE id = #{id}
</select><select id="getStudentsByTeacherId" resultType="Student">SELECT * FROM student WHERE teacher_id = #{id}
</select>
懒加载的触发条件
懒加载的触发条件是访问关联对象的属性。例如:
Student student = studentMapper.getStudent(1);
// 此时还未加载teacherSystem.out.println(student.getTeacher().getName());
// 此时才会执行teacher的查询
懒加载的优缺点
优点:
- 减少不必要的查询:只加载需要的数据
- 提高性能:减少数据库访问次数
- 节省内存:避免加载大量不使用的数据
缺点:
- N + 1查询问题:如果遍历多个主对象并访问关联对象,会导致多次查询
- 调试复杂性:由于加载时机不明确,可能增加调试难度
- 可能引发异常:如果在Session关闭后访问懒加载对象会抛出异常
解决N + 1查询问题的方法
- 使用批量加载(Batch Loading)
- 在特定场景下关闭懒加载,使用联合查询
- 使用Mybatis的@Lazy注解控制加载行为
注意事项
- Session生命周期:懒加载需要在Session未关闭时使用,否则会抛出异常
- 序列化问题:懒加载对象序列化后再反序列化会失去懒加载特性
- 性能监控:需要监控实际使用中的性能,避免过度使用导致性能下降
懒加载是Mybatis中一个强大的特性,合理使用可以显著提高应用性能,但也需要根据实际场景谨慎使用
示例
https://blog.csdn.net/qq_52331401/article/details/148306528?spm=1001.2014.3001.5502
我在上面文章中写了一对多查询demo,下面写一个方法测试懒加载的效果
对应sql语句
select teacher.*, student.* from student right join teacher on student.t_id = teacher.id;
当只需输出Tname时
可以看到控制台只查询了Tname
当输出全部信息时
可以看到整条sql语句都被执行了