1.什么是延迟加载?
当我们在使用MyBatis进行数据库查询时,通常会使用一种称为“立即加载”的方式。 这意味着当查询主对象时,MyBatis会立即加载该对象及其关联对象的所有数据。 但是,有时关联对象的数据可能会很大,而且并不一定每次都需要完整加载所有的关联对象数据。 这就是延迟加载的作用。 延迟加载是一种性能优化技术,它允许在需要的时候才去加载关联对象的数据,而不是在查询主对象时就一次性加载所有关联对象。 这样可以避免不必要的数据库查询,提高查询性能和减轻数据库负载。
开启延迟加载后,在真正使用数据的时候才发起级联查询,不用的时候不查询。
1.1.局部配置延迟加载
在xxx.xml文件<resultMap><collection></collection> </resultMap>标签中配置
property="accounts":属性名 ofType="com.by.pojo.Account":集合的泛型,等价于resultType select="com.by.mapper.AccountMapper.selectAccountByUid":要调用的select标签的id column="id":传递给select查询的参数 fetchType="lazy":延迟加载,默认没有开启延迟加载
1.2.全局配置延迟加载
在mybatis-config.xml文件中<configuration></configuration>标签配置
<settings>
<!--开启懒加载(开启延迟加载)-->
<setting name="lazyLoadingEnabled" value="true"/>
<!-- false 深入式延迟加载 true 侵入式延迟加载 -->
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
2.案例代码
2.1.pojo
public class User {
private Integer id;
private String username;
private Date birthday;
private String sex;
private String address;
private List<Account> accounts;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public List<Account> getAccounts() {
return accounts;
}
public void setAccounts(List<Account> accounts) {
this.accounts = accounts;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", birthday=" + birthday +
", sex='" + sex + '\'' +
", address='" + address + '\'' +
", accounts=" + accounts +
'}';
}
}
2.2.Mapper
public interface UserMapper {
User getUserById(Integer id);
}
<?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">
<!--namespace:隔离sql,一般是接口名称的全类名-->
<mapper namespace="com.zh.mapper.UserMapper">
<resultMap id="getUserByIdResultMap" type="user">
<id column="id" property="id"></id>
<result column="username" property="username"></result>
<result column="sex" property="sex"></result>
<result column="birthday" property="birthday"></result>
<result column="address" property="address"></result>
<!--延迟加载的一对多-->
<!--
property="accounts":属性名
ofType="com.by.pojo.Account":集合的泛型,等价于resultType
select="com.by.mapper.AccountMapper.selectAccountByUid":要调用的select标签的id
column="id":传递给select查询的参数
fetchType="lazy":延迟加载,默认没有开启延迟加载
-->
<collection property="accounts"
ofType="com.zh.pojo.Account"
select="com.zh.mapper.AccountMapper.selectAccountByUid"
column="id">
</collection>
</resultMap>
<select id="getUserById" resultMap="getUserByIdResultMap">
select * from user where id=#{id}
</select>
</mapper>
2.3.测试
public class MyBatisTest {
private SqlSession session;
private InputStream inputStream;
@Before
public void before() throws Exception{
//加载配置文件
String resource = "mybatis-config.xml";
inputStream = Resources.getResourceAsStream(resource);
//创建一个sqlSessionFactory
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//获得数据库的会话实例
session = sessionFactory.openSession();
}
/**
* 延迟加载:一对多
* */
@Test
public void testGetUserById() throws Exception{
//返回接口的代理类
UserMapper userMapper = session.getMapper(UserMapper.class);
User user = userMapper.getUserById(41);
System.out.println(user.getUsername());
List<Account> accounts = user.getAccounts();
accounts.forEach(account -> System.out.println(account));
}
@After
public void close() throws Exception{
//关闭资源
inputStream.close();
session.close();
}
}