什么是延迟加载?
讲延迟加载也叫懒加载。延迟加载就是在关联查询时,利用延迟加载,先加载主信息,使用关联信息时再去加载关联信息。
resultMap中的association和collection标签具有延迟加载的功能。
配置延迟加载
在SqlMapConfig.xml文件,<settings>标签中设置下延迟加载。
<settings>
<!--开启延迟加载 -->
<setting name="lazyLoadingEnabled" value="true" />
<!--关闭积极加载 -->
<setting name="aggressiveLazyLoading" value="false" />
</settings>
实现延迟加载示例
现在有三张表,文章表:article;用户表:user;文章标签表:tag。
CREATE TABLE `article` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '文章id',
`title` varchar(100) NOT NULL COMMENT '标题',
`userId` int(11) NOT NULL COMMENT '用户id',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COMMENT='文章表';
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键id',
`name` varchar(10) NOT NULL COMMENT '姓名',
`gender` char(1) DEFAULT NULL COMMENT '性别,M-男,F-女',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COMMENT='用户表';
CREATE TABLE `tag` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键id',
`name` varchar(20) NOT NULL COMMENT '标签名称',
`articleId` int(11) NOT NULL COMMENT '文章id',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='文章标签表';
article表中一条记录对应user中一条记录,对应tag表中多条记录,现在查询article表信息时也要查询article对应的user和tag。
(1)编写三张表对应的实体类
Article实体类中包含user和tags,如下:
package com.lzgsea.entity;
import java.util.List;
public class Article {
private Integer id;
private String title;
private Integer userId;
private User user;
private List<Tag> tags;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public Integer getUserId() {
return userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public List<Tag> getTags() {
return tags;
}
public void setTags(List<Tag> tags) {
this.tags = tags;
}
@Override
public String toString() {
return "Article [id=" + id + ", title=" + title + ", userId=" + userId + ", user=" + user + ", tags=" + tags
+ "]";
}
}
(2)编写sql语句XML文件
<?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="com.lzgsea.mapper.ArticleMapper">
<resultMap id="BaseResultMap" type="com.lzgsea.entity.Article">
<id column="id" property="id" />
<result column="title" property="title" />
<result column="userId" property="userId" />
<association property="user" column="userId" select="getUser"></association>
<collection property="tags" column="userId" select="getTags"></collection>
</resultMap>
<select id="getList" resultMap="BaseResultMap">
select * from article
</select>
<select id="getUser" resultType="com.lzgsea.entity.User">
select * from user
</select>
<select id="getTags" resultType="com.lzgsea.entity.Tag">
select * from tag
</select>
</mapper>
注意:由于是懒加载是分开查询,所以我们的每个select 映射也需要分开写。 association查询是一对一关系,collection查询是一对多关系。
association 和 collection 标签中的 column 和select属性:
select: 需要调用的 select 映射的 id ;
column : 传递给 select 映射的 参数。
(3)测试
package com.lzgsea.test;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
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 com.lzgsea.entity.Article;
import com.lzgsea.mapper.ArticleMapper;
public class MyTest {
private static SqlSessionFactory sqlSessionFactory;
public static SqlSession getSqlSession() {
if (sqlSessionFactory == null) {
String resource = "SqlMapConfig.xml";
InputStream inputStream = null;
try {
inputStream = Resources.getResourceAsStream(resource);
} catch (IOException e) {
e.printStackTrace();
}
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
return sqlSessionFactory.openSession();
}
public static void main(String[] args) {
SqlSession sqlSession = getSqlSession();
try {
ArticleMapper articleMapper = sqlSession.getMapper(ArticleMapper.class);
List<Article> list = articleMapper.getList();
for (Article a : list) {
System.out.println(a.getTitle());
System.out.println(a.getTags());
System.out.println(a.getUser());
}
} finally {
sqlSession.close();
}
}
}
user和tags只有在我们使用时才会从数据库中查询,不使用时不会查询。上面代码中我们调用getUser()时,mybatis才会查询查询user表,调用getTags()时才会查询tag表。
如果我们想在查询article表时就直接查询user表和tag表,只要将aggressiveLazyLoading设为true就可以了。