MyBatis延遲加載策略深入探究
有兩種寫法來表示查詢信息,分別是鏈表查詢和分步查詢的方法。那么既然我么能用一個(gè)SQL語句能夠執(zhí)行完,那為什么還要分開來寫呢?
原因很簡單:可以發(fā)現(xiàn)如果我們把他們連在一起那么他們就是一個(gè)多表查詢語句,如果不放在一起執(zhí)行,那那就是單獨(dú)一個(gè)表的查詢語句。但是這需要我們設(shè)置mybatis的延遲加載(懶加載)
分步查詢的優(yōu)點(diǎn)
**可以實(shí)現(xiàn)延遲加載,**但是必須在核心配置文件中設(shè)置全局配置信息
lazyLoadingEnabled:延遲加載的全局開關(guān)。當(dāng)開啟時(shí),所有關(guān)聯(lián)對象都會(huì)延遲加載
aggressiveLazyLoding:當(dāng)開啟時(shí),任何方式的調(diào)用都會(huì)加載該對象的所有屬性。否則,該屬性會(huì)按需加載 ,此時(shí)就可以實(shí)現(xiàn)按需加載,需要獲取的數(shù)據(jù)是什么,就只會(huì)執(zhí)行相應(yīng)的sql.此時(shí)會(huì)通過association和collection中的fetchType屬性設(shè)置當(dāng)前的分步查詢是否使用懶加載
fetchType=“lazy(延遲加載) | eager(立即加載)”
在主配置文件當(dāng)中設(shè)置延遲加載
延遲加載:在SqlMapConfig.xml中配置延遲加載文件
<settings>
<setting name="logImpl" value="STDOUT_LOGGING" /> <!-- 打印日志到控制臺(tái)上 -->
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="aggressiveLazyLoading" value="false"/> <!-- false才會(huì)按需加載,不開啟調(diào)用所有的對象 -->
</settings>

在studentDao.xml當(dāng)中設(shè)置分步查詢

測試結(jié)果
此時(shí)開啟了懶加載,實(shí)現(xiàn)了分布查詢

如何使用
public class UserDO {
private Integer userId;
private String username;
private String password;
private String nickname;
private List<PermitDO> permitDOList;
public UserDO() {}
}<resultMap id="BaseMap" type="org.apache.ibatis.study.entity.UserDO">
<id column="user_id" jdbcType="INTEGER" property="userId" />
<result column="username" jdbcType="VARCHAR" property="username" />
<result column="password" jdbcType="VARCHAR" property="password" />
<result column="nickname" jdbcType="VARCHAR" property="nickname"/>
<collection property="permitDOList" column="user_id" select="getPermitsByUserId"
fetchType="lazy">
</collection>
</resultMap>
<resultMap id="PermitBaseMap" type="org.apache.ibatis.study.entity.PermitDO">
<id column="id" jdbcType="INTEGER" property="id"/>
<result column="code" jdbcType="VARCHAR" property="code"/>
<result column="name" jdbcType="VARCHAR" property="name"/>
<result column="type" jdbcType="TINYINT" property="type"/>
<result column="pid" jdbcType="INTEGER" property="pid"/>
</resultMap>
<select id="getByUserId2" resultMap="BaseMap">
select * from user
where user_id = #{userId}
</select>
<select id="getPermitsByUserId" resultMap="PermitBaseMap">
select p.*
from user_permit up
inner join permit p on up.permit_id = p.id
where up.user_id = #{userId}
</select>通過fetchType=lazy指定子查詢getPermitsByUserId使用懶加載,這樣的話就不用管全局配置lazyLoadingEnabled是true還是false了。當(dāng)然這里可以直接用多表關(guān)聯(lián)查詢不使用子查詢,使用方法在這篇文章
測試代碼
public class Test {
public static void main(String[] args) throws IOException {
try (InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml")) {
// 構(gòu)建session工廠 DefaultSqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
UserDO userDO = userMapper.getByUserId2(1);
System.out.println(userDO);
}
}
}結(jié)果如下,打了斷點(diǎn)可以看到原userDO對象已被代理并且permitDOList是null需要調(diào)用get方法才會(huì)去查詢拿到值,咳咳這邊之前直接運(yùn)行顯示是已經(jīng)把permitDOList查詢出來了,想了半天啥原因后來才發(fā)現(xiàn)println會(huì)調(diào)用userDO對象的toString方法,而toString方法也會(huì)走代理方法直接去調(diào)用子查詢的


延遲加載的好處
延遲加載主要能解決mybatis的N+1問題,什么是N+1問題其實(shí)叫1+N更為合理,以上面的業(yè)務(wù)例子來說就是假設(shè)一次查詢出來10000個(gè)用戶,那么還需要針對這10000個(gè)用戶使用子查詢getPermitsByUserId獲取每個(gè)用戶的權(quán)限列表,需要10000次查詢,總共10001次,真實(shí)情況下你可能并不需要每個(gè)子查詢的結(jié)果,這樣就浪費(fèi)數(shù)據(jù)庫連接資源了。如果使用延遲加載的話就相當(dāng)于不用進(jìn)行這10000次查詢,因?yàn)樗堑鹊侥阏嬲褂玫臅r(shí)候才會(huì)調(diào)用子查詢獲取結(jié)果。
到此這篇關(guān)于MyBatis延遲加載策略深入探究的文章就介紹到這了,更多相關(guān)MyBatis延遲加載內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot+阿里云OSS實(shí)現(xiàn)在線視頻播放的示例
這篇文章主要介紹了SpringBoot+阿里云OSS實(shí)現(xiàn)在線視頻播放的示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-11-11
Spring中的REST分頁的實(shí)現(xiàn)代碼
本文將介紹在REST API中實(shí)現(xiàn)分頁的基礎(chǔ)知識(shí)。我們將專注于使用Spring Boot和Spring Data 在Spring MVC中構(gòu)建REST分頁,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2019-01-01
Java基礎(chǔ)學(xué)習(xí)之構(gòu)造方法詳解
這篇文章主要為大家詳細(xì)介紹了Java基礎(chǔ)學(xué)習(xí)中構(gòu)造方法的概述及注意事項(xiàng),文中的示例代碼講解詳細(xì),對我們學(xué)習(xí)Java有一定幫助,需要的可以參考一下2022-08-08
Java多維數(shù)組和Arrays類方法總結(jié)詳解
這篇文章主要介紹了Java多維數(shù)組和Arrays類方法總結(jié)詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-03-03
JAVA 實(shí)現(xiàn)磁盤文件加解密操作的示例代碼
這篇文章主要介紹了JAVA 實(shí)現(xiàn)磁盤文件加解密操作的示例代碼,幫助大家利用Java實(shí)現(xiàn)文件的加解密,感興趣的朋友可以了解下2020-09-09
Idea安裝bpmn插件actiBPM的詳細(xì)過程(解決高版本無法安裝actiBPM插件)
這篇文章主要介紹了Idea安裝bpmn插件actiBPM的詳細(xì)過程(解決高版本無法安裝actiBPM插件)的問題,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-01-01
Java實(shí)現(xiàn)讀取設(shè)置pdf屬性信息
這篇文章主要為大家詳細(xì)介紹了如何使用Java實(shí)現(xiàn)讀取設(shè)置pdf屬性信息,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2025-01-01
SpringBoot實(shí)現(xiàn)自動(dòng)配置的方式詳解
Spring Boot 自動(dòng)配置 是其核心特性之一,它通過智能化的默認(rèn)配置減少了開發(fā)者的工作量,自動(dòng)配置的原理基于條件化配置和 Spring 的 @Configuration 機(jī)制,本文給大家講解了SpringBoot實(shí)現(xiàn)自動(dòng)配置的過程,需要的朋友可以參考下2025-04-04

