Mybatis 延遲加載

什麼是延遲加載?

講延遲加載也叫懶加載。延遲加載就是在關聯查詢時,利用延遲加載,先加載主信息,使用關聯信息時再去加載關聯信息。

 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就可以了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章