1.延迟加载是什么
延迟加载其实就是将数据加载时机推迟,比如推迟嵌套查询的执行时机。
2.为什么要进行延迟加载
在Mybatis中经常用到关联查询,但是并不是任何时候都需要立即返回关联查询结果。比如查询订单信息,并不一定需要及时返回订单对应的产品信息,查询商品分类信息并不一定要及时返回该类别下有哪些产品,这种情况一下需要一种机制,当需要查看时,再执行查询,返回需要的结果集,这种需求在Mybatis中可以使用延迟加载机制来实现。延迟加载可以实现先查询主表,按需实时做关联查询,返回关联表结果集,一定程度上提高了效率。
3.如何进行延迟加载
首先要开启Mybatis对延迟加载的支持
根据官方文档的描述,在mybatis的配置文件中开启延迟加载
<settings>
<!--开启二级缓存-->
<setting name="cacheEnabled" value="true"/>
<!--开启mybatis支持延迟加载-->
<setting name="lazyLoadingEnabled" value="true"/>
<!--false表示按需加载,true表示立即加载-->
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
既然是管理查询,那么肯定在一个实体类中有其他实体类的映射
import java.io.Serializable;
import java.util.List;
/**
* Created on 16:12 23/11/2019
* Description:
* user的实体类
*
* @author Weleness
*/
public class User implements Serializable {
private Integer id;
private String username;
private String password;
//一对多关系映射
private List<Account> account;
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 String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public List<Account> getAccount() {
return account;
}
public void setAccount(List<Account> account) {
this.account = account;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
", account=" + account +
'}';
}
}
要实现延迟加载,我们可以使用分段查询的方式,
分段查询又有两种方式,第一种是XML文档的配置方式
标注上属性fetchType=“lazy”
<?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" >
<mapper namespace="weleness.dao.IUserDao">
<!--开启UserDao支持二级缓存-->
<!--<cache/>-->
<resultMap id="userMap" type="user">
<!--property对应实体类中的映射签面 column对应需要传过去的参数-->
<collection property="account" column="id" select="weleness.dao.IAccountDao.findAccountById" ofType="weleness.pojo.Account" fetchType="lazy"/>
</resultMap>
<select id="findAll" useCache="true" resultMap="userMap">
select * from user;
</select>
</mapper>
Account对应的方法配置
<?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" >
<mapper namespace="weleness.dao.IAccountDao">
<select id="findAccountById" resultType="account">
select * from account where uid = #{id}
</select>
</mapper>
测试代码,先不进行对account值的获取,先查找所有用户
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Before;
import org.junit.Test;
import weleness.dao.IUserDao;
import weleness.pojo.User;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
/**
* Created on 16:14 23/11/2019
* Description:
*
* @author Weleness
*/
public class UserTest {
SqlSession sqlSession = null;
IUserDao dao = null;
SqlSessionFactory factory = null;
@Before
public void init() throws IOException {
//导入配置文件
InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
//交给构建者构建工厂对象
factory = new SqlSessionFactoryBuilder().build(in);
sqlSession = factory.openSession();
dao = sqlSession.getMapper(IUserDao.class);
}
@Test
public void testFindAll(){
List<User> all = dao.findAll();
// for (User user : all) {
// System.out.println(user.getAccount());
// }
//List<Account> account = all.get(0).getAccount();
//System.out.println(account);
//String username = all.get(0).getUsername();
//System.out.println(username);
}
}
控制台输出,可以看到并没进行account的sql操作
让我们来获取account的值
@Test
public void testFindAll(){
List<User> all = dao.findAll();
for (User user : all) {
System.out.println(user.getAccount());
}
可以看到,mybatis根据查询来的user的id,一条一条进行了id的查询
第二种是注解的方式配置
在要查询的方法上面加上@Results注解,里面有一个嵌套注解many,然后就和xml配置的方式差不多,当然,也要首先在配置文件中开启支持。
@Results(id = "userMap" , value = {@Result(property = "account",column = "id" , many = @Many(select = "weleness.dao.findAccountById",fetchType = FetchType.LAZY))})
@Select("select * from user")
List<User> findAll();