什么是延迟加载
延迟加载(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());
}
}
}延迟加载执行流程解析
- 执行mapper.findall()时,mybatis 只查询 account 表,获取账户基本信息
- 此时 account 对象中的 user 属性为代理对象(尚未查询数据库)
- 当执行account.getuser().getname()时,才会触发 user 查询
- 执行com.qcby.mapper.usermapper.findbyid方法,传入 uid 参数
- 获取用户信息并赋值给 account 的 user 属性
延迟加载的优点
- 减少不必要的 sql 查询,提高数据库性能
- 减少内存占用,只加载当前需要的数据
- 适用于关联数据较多但不一定都会使用的场景
注意事项
- 延迟加载只对关联查询有效(一对一、一对多等)
- 必须在核心配置文件中开启延迟加载开关
- 如果提前关闭 sqlsession,会导致延迟加载失败(无法执行后续查询)
- 延迟加载通过 cglib 或 jdk 动态代理实现,关联对象是代理对象
到此这篇关于mybatis延迟加载的实现示例的文章就介绍到这了,更多相关mybatis延迟加载内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论