學(xué)習(xí)mybatis的第四天

1.Mybatis 延遲加載策略

問題:在一對(duì)多中,當(dāng)我們有一個(gè)用戶,該用戶有100個(gè)賬戶,

①在查詢用戶的時(shí)候,要不要把關(guān)聯(lián)的賬戶查詢出來?

②在查詢賬戶的時(shí)候,要不要把關(guān)聯(lián)的用戶信息查詢出來?

解決方案是:

①在查詢用戶的時(shí)候,用戶下的賬戶信息應(yīng)該是什么時(shí)候使用,什么時(shí)候查詢。(延遲加載)

②在查詢賬戶的時(shí)候,賬戶下的所屬用戶信息應(yīng)該是隨賬戶一起查詢出來。(立即加載)

1.1什么為延遲加載:

延遲加載:就是在需要用到數(shù)據(jù)時(shí)才進(jìn)行加載,不需要用到數(shù)據(jù)時(shí)就不加載數(shù)據(jù)。按需加載,延遲加載也稱懶加載.

好處:先從單表查詢,需要時(shí)再?gòu)年P(guān)聯(lián)表去關(guān)聯(lián)查詢,大大提高數(shù)據(jù)庫性能,因?yàn)椴樵儐伪硪汝P(guān)聯(lián)查詢多張表速度要快。

缺點(diǎn):因?yàn)橹挥挟?dāng)需要用到數(shù)據(jù)時(shí),才會(huì)進(jìn)行數(shù)據(jù)庫查詢,這樣在大批量數(shù)據(jù)查詢時(shí),因?yàn)椴樵児ぷ饕惨?/p>

時(shí)間,所以可能造成用戶等待時(shí)間變長(zhǎng),造成用戶體驗(yàn)下降。

*注意:

一對(duì)一、多對(duì)一通常情況下采用立即加載

多對(duì)多、一對(duì)多通常情況下采用延遲加載

1.2用延遲加載實(shí)現(xiàn)需求:

需求:

查詢賬戶(Account)信息并且關(guān)聯(lián)查詢用戶(User)信息。如果先查詢賬戶(Account)信息即可滿足要求,當(dāng)我們需要查詢用戶(User)信息時(shí)再查詢用戶(User)信息。把對(duì)用戶(User)信息的按需去查詢就是延遲加載。

mybatis第三天實(shí)現(xiàn)多表操作時(shí),使用了resultMap來實(shí)現(xiàn)一對(duì)一,一對(duì)多,多對(duì)多關(guān)系的操作。主要是通過 association、collection 實(shí)現(xiàn)一對(duì)一及一對(duì)多映射。association、collection 具備延遲加載功能。

在全局的xml文件SqlMapConfig文件中配置:

<settings>

<setting name="lazyLoadingEnabled" value="true"/>

<setting name="aggressiveLazyLoading" value="false"/>

</settings>

①使用association完成延遲加載:

需求:

查詢賬戶信息同時(shí)查詢用戶信息(在多對(duì)一即mybatis中的一對(duì)一的情況下完成延遲加載)。

IAccountDao接口中的方法:

public interface IAccountDao {

/*** 查詢所有賬戶,同時(shí)獲取賬戶的所屬用戶名稱以及它的地址信息

* @return

*/

List<Account> findAll( );

}

IAccoutDao.xml映射文件的配置:

<!-- 建立對(duì)應(yīng)關(guān)系 -->

<mapper? namespace = "com.itheima.dao.IAccountDao">

<resultMap type="account" id="accountMap">

<id column="aid" property="id"/>

<result column="uid" property="uid"/>

<result column="money" property="money"/>

<!-- 它是用于指定從表方的引用實(shí)體屬性的 -->

<association property="user"? javaType="user"

select="com.itheima.dao.IUserDao.findById"? column="uid">

</association>

</resultMap>

<select id="findAll" resultMap="accountMap">

????select * from account

</select>

</mapper>

select : 填寫我們要調(diào)用的 select 映射的 id,即在IUserDao接口中的findById的方法

column : 填寫我們要傳遞給 select 映射的參數(shù),傳給findById方法的參數(shù),在這里肯定為account表中的uid

IUserDao接口中的方法:

public interface IUserDao {

/**

* 根據(jù) id 查詢

* @param userId*

@return

*/

User findById(Integer id);

}? ?

IUserDao.xml映射文件的配置:

<mapper namespace="com.itheima.dao.IUserDao">

<!-- 根據(jù) id 查詢 -->

<select id="findById" resultType="user" parameterType="int" >

select * from user where id = #{uid}

</select>

</mapper>

②使用collection完成延遲加載:

需求:

完成加載用戶對(duì)象時(shí),查詢?cè)撚脩羲鶕碛械馁~戶信息(在一對(duì)多的情況下完成延遲加載)

IUserDao接口中的方法:

/**

*查詢所有用戶,同時(shí)獲取出每個(gè)用戶下的所有賬戶信息

* @return

*/

List<User> findAll(? );

IUserDao.xml文件的配置:

<resultMap type="user" id="userMap">

?????<id column="id" property="id"></id>

????<result column="username" property="username"/>

????<result column="address" property="address"/>

????<result column="sex" property="sex"/>

????<result column="birthday" property="birthday"/>

<!-- collection 是用于建立一對(duì)多中集合屬性的對(duì)應(yīng)關(guān)系

ofType 用于指定集合元素的數(shù)據(jù)類型

select 是用于指定查詢賬戶的唯一標(biāo)識(shí)(賬戶的 dao 全限定類名加上方法名稱)

column 是用于指定使用哪個(gè)字段的值作為條件查詢 -->

<collection property="accounts"? ? ofType="account"? ?

select="com.itheima.dao.IAccountDao.findByUid"? ?column="id">

</collection>

</resultMap>


<!-- 配置查詢所有操作 -->

<select id="findAll" resultMap="userMap">

select * from user

</select>

*注意:

<collection> 標(biāo)簽 :

主要用于加載關(guān)聯(lián)的集合對(duì)象

select 屬性 :

用于指定查詢 account 列表的 sql 語句,所以填寫的是該 sql 映射的 id

column 屬性 :

用于指定 select 屬性的 sql 語句的參數(shù)來源,上面的參數(shù)來自于 user 的 id 列,所以就寫成 id 這一個(gè)字段名了

IAccountDao接口中的方法:

/**

* 根據(jù)用戶 id 查詢賬戶信息

* @param uid

* @return

*/

List<Account>? ?findByUid(Integer uid);?

IAccountDao.xml配置文件:

<!-- 根據(jù)用戶 id 查詢賬戶信息 -->

<select id="findByUid"? resultType="account"? ?parameterType="int">

????????select * from account where uid = #{uid}

</select>

2.Mybatis中的緩存機(jī)制

? ? ? ?像大多數(shù)的持久化框架一樣,Mybatis 也提供了緩存策略,通過緩存策略來減少數(shù)據(jù)庫的查詢次數(shù),從而提

高性能。

????????Mybatis 中緩存分為一級(jí)緩存,二級(jí)緩存。

什么是緩存:存在于內(nèi)存中的臨時(shí)數(shù)據(jù);

為什么使用緩存:減少和數(shù)據(jù)庫交換的次數(shù),提高執(zhí)行效率;

適用于緩存的數(shù)據(jù):經(jīng)常查詢的數(shù)據(jù)并且不經(jīng)常改變,數(shù)據(jù)的正確與否對(duì)最終的結(jié)果影響不大的;

不適用于緩存的數(shù)據(jù):經(jīng)常改變的數(shù)據(jù),數(shù)據(jù)的正確與否對(duì)最終的結(jié)果影響很大的;

2.1Mybatis中的一級(jí)緩存:

一級(jí)緩存是 SqlSession對(duì)象級(jí)別的緩存,只要 SqlSession對(duì)象沒有 flush 或 close,它就存在。

原理:當(dāng)我們執(zhí)行查詢之后,查詢結(jié)果會(huì)存入到SqlSession對(duì)象為我們提供的一塊區(qū)域中。該區(qū)域的結(jié)構(gòu)是一個(gè)Map,當(dāng)我們?cè)俅尾樵兿嗤臄?shù)據(jù)時(shí),mybatis會(huì)先去SqlSession中查詢是否有,有的話直接拿出來使用。當(dāng)SqlSession對(duì)象消失時(shí),mybatis的一級(jí)緩存也就消失了。

一級(jí)緩存的分析:

一級(jí)緩存是 SqlSession 范圍的緩存,當(dāng)調(diào)用 SqlSession 的修改,添加,刪除,commit( ),close( )等方法時(shí),就會(huì)清空一級(jí)緩存。


分析圖

????????第一次發(fā)起查詢用戶 id 為 1 的用戶信息,先去找緩存中是否有 id 為 1 的用戶信息,如果沒有,從數(shù)據(jù)庫查

詢用戶信息。

????????得到用戶信息,將用戶信息存儲(chǔ)到一級(jí)緩存中。

????????如果 sqlSession 去執(zhí)行 commit 操作(執(zhí)行插入、更新、刪除),清空 SqlSession 中的一級(jí)緩存,這樣

做的目的為了讓緩存中存儲(chǔ)的是最新的信息,避免臟讀。

????????第二次發(fā)起查詢用戶 id 為 1 的用戶信息,先去找緩存中是否有 id 為 1 的用戶信息,緩存中有,直接從緩存

中獲取用戶信息。

2.2Mybatis中的二級(jí)緩存:

? ? ?二級(jí)緩存:存放的內(nèi)容是數(shù)據(jù)(JSON格式),而不是對(duì)象,會(huì)創(chuàng)建新對(duì)象,進(jìn)行存改;? ??

?????二級(jí)緩存是 mapper 映射級(jí)別的緩存,多個(gè) SqlSession 去操作同一個(gè) Mapper 映射的 sql 語句,多個(gè)SqlSession 可以共用二級(jí)緩存,二級(jí)緩存是跨 SqlSession 的。指的是mybatis中SqlSessionFactory對(duì)象的緩存。由同一個(gè)SqlSessionFactory對(duì)象創(chuàng)建的SqlSession共享其緩存。

二級(jí)緩存結(jié)構(gòu)圖

????????首先開啟 mybatis 的二級(jí)緩存。

????????sqlSession1 去查詢用戶信息,查詢到用戶信息會(huì)將查詢數(shù)據(jù)存儲(chǔ)到二級(jí)緩存中。

????????如果 SqlSession3 去執(zhí)行相同 mapper 映射下 sql,執(zhí)行 commit 提交,將會(huì)清空該 mapper 映射下的二級(jí)緩存區(qū)域的數(shù)據(jù)。

????????sqlSession2 去查詢與 sqlSession1 相同的用戶信息,首先會(huì)去緩存中找是否存在數(shù)據(jù),如果存在直接從

緩存中取出數(shù)據(jù)。

? ? ? ? 使用步驟:

? ? ? ? ?①讓mybatis框架支持二級(jí)緩存,在全局配置文件中配置:

<settings>

<setting name = "cacheEnable"? value ="true"/>

</settings>

????????②讓當(dāng)前映射文件支持二級(jí)緩存,配置:

??<mapper namespace="com.itheima.dao.IUserDao">

<!-- 開啟二級(jí)緩存的支持 -->

<cache></cache>

</mapper>

? ? ? ③讓當(dāng)前的操作支持二級(jí)緩存,在select標(biāo)簽中配置:

<!-- 根據(jù) id 查詢 -->

<select id="findById"? resultType="user"? parameterType="int"? useCache="true">

select * from user where id = #{uid}

</select>

將 UserDao.xml 映射文件中的<select>標(biāo)簽中設(shè)置 useCache=”true”代表當(dāng)前這個(gè) statement 要使用 二級(jí)緩存,如果不使用二級(jí)緩存可以設(shè)置為 false。

*注意:針對(duì)每次查詢都需要最新的數(shù)據(jù) sql,要設(shè)置成 useCache=false,禁用二級(jí)緩存。

二級(jí)緩存注意事項(xiàng):當(dāng)我們?cè)谑褂枚?jí)緩存時(shí),所緩存的類一定要實(shí)現(xiàn) java.io.Serializable 接口,這種就可以使用序列化方式來保存對(duì)象。

3.Mybatis中的注解開發(fā):

3.1 mybatis 的常用注解說明:

@Insert:實(shí)現(xiàn)新增

@Update:實(shí)現(xiàn)更新

@Delete:實(shí)現(xiàn)刪除

@Select:實(shí)現(xiàn)查詢

@Result:實(shí)現(xiàn)結(jié)果集封裝

@Results:可以與@Result 一起使用,封裝多個(gè)結(jié)果集

@ResultMap:實(shí)現(xiàn)引用@Results 定義的封裝

@One:實(shí)現(xiàn)一對(duì)一結(jié)果集封裝

@Many:實(shí)現(xiàn)一對(duì)多結(jié)果集封裝

@SelectProvider: 實(shí)現(xiàn)動(dòng)態(tài) SQL 映射

@CacheNamespace:實(shí)現(xiàn)注解二級(jí)緩存的使用

注解開發(fā)測(cè)試使用的注意事項(xiàng):

采用注解開發(fā)時(shí),在全局配置文件中配置:

<mappers>

<mapper class = "com.itheima.dao.IUserDao"/>

</mappers>

或者直接配置:

<mappers>

????????<package name="com.itheima.dao"/>

</mappers>

*注意:采用注解開發(fā)時(shí),不能在同一個(gè)文件名稱下dao進(jìn)行xml開發(fā),即使使用resource屬性也不能。

如:dao接口在com.itheima.dao下,而對(duì)應(yīng)接口的映射配置文件xml也在resources的com.itehima.dao目錄下,此時(shí)就會(huì)報(bào)錯(cuò),要么把xml移到別的目錄,然后刪除整個(gè)目錄文件,要么直接刪除文件和文件目錄。

3.2使用注解實(shí)現(xiàn)復(fù)雜關(guān)系映射開發(fā):

????????實(shí)現(xiàn)復(fù)雜關(guān)系映射之前我們可以在映射文件中通過配置<resultMap>來實(shí)現(xiàn),在使用注解開發(fā)時(shí)我們需要借

助@Results 注解,@Result 注解,@One 注解,@Many 注解。

????????復(fù)雜關(guān)系映射的注解說明:

@Results 注解? ?代替的是標(biāo)簽<resultMap>

@Resutl 注解? ? 代替了 <id> 標(biāo)簽和<result> 標(biāo)簽

@Result 中 屬性介紹:

????????id 是否是主鍵字段

????????column 數(shù)據(jù)庫的列名

????????property 需要裝配的屬性名

????????one 需要使用的@One 注解(@Result(one=@One)()))

????????many 需要使用的@Many 注解(@Result(many=@many)()))

@one中的屬性介紹:??

? ? ? ?@One 注解(一對(duì)一) 代替了<assocation> 標(biāo)簽,是多表查詢的關(guān)鍵,在注解中用來指定子查詢返回單一對(duì)象。

????????select? ?指定用來多表查詢的 sqlmapper

????????fetchType 會(huì)覆蓋全局的配置參數(shù) FetchType.LAZY(延遲加載)或者FetchType.EAGER(立即加載)

例如:

IAccountDao

*注意:

此時(shí)最后一個(gè)@Result注解中,column屬性指定用來多表查詢的sqlmapper的參數(shù)? ,

@Many 注解(多對(duì)一)

????????代替了<Collection> 標(biāo)簽, 是是多表查詢的關(guān)鍵,在注解中用來指定子查詢返回對(duì)象集合。

注意:聚集元素用來處理“一對(duì)多”的關(guān)系。需要指定映射的 Java 實(shí)體類的屬性,屬性的 javaType(一般為 ArrayList)但是注解中可以不定義;

例如:

IUserDao

3.3 mybatis 基于注解的二級(jí)緩存:

①.在全局配置文件SqlMapConfig.xml中配置開啟二級(jí)緩存:

<!-- 配置二級(jí)緩存 -->

<settings>

????<!-- 開啟二級(jí)緩存的支持 -->

????<setting name="cacheEnabled" value="true"/>

</settings>

②. 在持久層接口中使用注解配置二級(jí)緩存:

@CacheNamespace(blocking=true)//mybatis 基于注解方式實(shí)現(xiàn)配置二級(jí)緩存


?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1. 簡(jiǎn)介 1.1 什么是 MyBatis ? MyBatis 是支持定制化 SQL、存儲(chǔ)過程以及高級(jí)映射的優(yōu)秀的...
    笨鳥慢飛閱讀 6,280評(píng)論 0 4
  • MyBatis 理論篇 [TOC] 什么是MyBatis ?MyBatis是支持普通SQL查詢,存儲(chǔ)過程和高級(jí)映射...
    有_味閱讀 3,186評(píng)論 0 26
  • 前言 主題是Mybatis一級(jí)和二級(jí)緩存的應(yīng)用及源碼分析。希望在本場(chǎng)chat結(jié)束后,能夠幫助讀者朋友明白以下三點(diǎn)。...
    余平的余_余平的平閱讀 1,431評(píng)論 0 12
  • 編寫日志輸出環(huán)境配置文件 在開發(fā)過程中,最重要的就是在控制臺(tái)查看程序輸出的日志信息,在這里我們選擇使用 log4j...
    我沒有三顆心臟閱讀 6,925評(píng)論 0 33
  • Hello JianShu ! 好吧,職業(yè)病又犯了??磥砦沂且粋€(gè)真正的程序猿。感覺我們的Hello world是萬...
    小強(qiáng)德美閱讀 266評(píng)論 1 0

友情鏈接更多精彩內(nèi)容