什麼是延遲加載?
講延遲加載也叫懶加載。延遲加載就是在關聯查詢時,利用延遲加載,先加載主信息,使用關聯信息時再去加載關聯信息。
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就可以了。