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

1.Mybatis 延遲加載策略

問(wèn)題:在一對(duì)多中航缀,當(dāng)我們有一個(gè)用戶序调,該用戶有100個(gè)賬戶芳誓,

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

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

解決方案是:

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

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

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ù)庫(kù)性能迫筑,因?yàn)椴樵儐伪硪汝P(guān)聯(lián)查詢多張表速度要快宪赶。

缺點(diǎn):因?yàn)橹挥挟?dāng)需要用到數(shù)據(jù)時(shí),才會(huì)進(jìn)行數(shù)據(jù)庫(kù)查詢脯燃,這樣在大批量數(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來(lái)實(shí)現(xiàn)一對(duì)一赚哗,一對(duì)多她紫,多對(duì)多關(guān)系的操作。主要是通過(guò) 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 : 填寫(xiě)我們要調(diào)用的 select 映射的 id疯潭,即在IUserDao接口中的findById的方法

column : 填寫(xiě)我們要傳遞給 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 語(yǔ)句相叁,所以填寫(xiě)的是該 sql 映射的 id

column 屬性 :

用于指定 select 屬性的 sql 語(yǔ)句的參數(shù)來(lái)源遵绰,上面的參數(shù)來(lái)自于 user 的 id 列,所以就寫(xiě)成 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 也提供了緩存策略椿访,通過(guò)緩存策略來(lái)減少數(shù)據(jù)庫(kù)的查詢次數(shù),從而提

高性能埠通。

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

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

為什么使用緩存:減少和數(shù)據(jù)庫(kù)交換的次數(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ì)象沒(méi)有 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中查詢是否有绍在,有的話直接拿出來(lái)使用。當(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 的用戶信息涡扼,如果沒(méi)有,從數(shù)據(jù)庫(kù)查

詢用戶信息盟庞。

????????得到用戶信息吃沪,將用戶信息存儲(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 語(yǔ)句粘优,多個(gè)SqlSession 可以共用二級(jí)緩存仇味,二級(jí)緩存是跨 SqlSession 的呻顽。指的是mybatis中SqlSessionFactory對(duì)象的緩存。由同一個(gè)SqlSessionFactory對(duì)象創(chuàng)建的SqlSession共享其緩存丹墨。

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

????????首先開(kāi)啟 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">

<!-- 開(kāi)啟二級(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 接口,這種就可以使用序列化方式來(lái)保存對(duì)象郑口。

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

3.1 mybatis 的常用注解說(shuō)明:

@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í)緩存的使用

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

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

<mappers>

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

</mappers>

或者直接配置:

<mappers>

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

</mappers>

*注意:采用注解開(kāi)發(fā)時(shí)犬性,不能在同一個(gè)文件名稱下dao進(jìn)行xml開(kāi)發(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)系映射開(kāi)發(fā):

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

助@Results 注解昂拂,@Result 注解,@One 注解抛猖,@Many 注解格侯。

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

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

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

@Result 中 屬性介紹:

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

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

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

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

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

@one中的屬性介紹:??

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

????????select? ?指定用來(lái)多表查詢的 sqlmapper

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

例如:

IAccountDao

*注意:

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

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

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

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

例如:

IUserDao

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

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

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

<settings>

????<!-- 開(kāi)啟二級(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)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市鹿霸,隨后出現(xiàn)的幾起案子排吴,更是在濱河造成了極大的恐慌,老刑警劉巖懦鼠,帶你破解...
    沈念sama閱讀 210,914評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件钻哩,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡肛冶,警方通過(guò)查閱死者的電腦和手機(jī)街氢,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評(píng)論 2 383
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)睦袖,“玉大人珊肃,你說(shuō)我怎么就攤上這事∠隗希” “怎么了近范?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,531評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)延蟹。 經(jīng)常有香客問(wèn)我评矩,道長(zhǎng),這世上最難降的妖魔是什么阱飘? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,309評(píng)論 1 282
  • 正文 為了忘掉前任斥杜,我火速辦了婚禮,結(jié)果婚禮上沥匈,老公的妹妹穿的比我還像新娘蔗喂。我一直安慰自己,他們只是感情好高帖,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,381評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布缰儿。 她就那樣靜靜地躺著,像睡著了一般散址。 火紅的嫁衣襯著肌膚如雪乖阵。 梳的紋絲不亂的頭發(fā)上宣赔,一...
    開(kāi)封第一講書(shū)人閱讀 49,730評(píng)論 1 289
  • 那天,我揣著相機(jī)與錄音瞪浸,去河邊找鬼儒将。 笑死,一個(gè)胖子當(dāng)著我的面吹牛对蒲,可吹牛的內(nèi)容都是我干的钩蚊。 我是一名探鬼主播,決...
    沈念sama閱讀 38,882評(píng)論 3 404
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼蹈矮,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼砰逻!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起泛鸟,我...
    開(kāi)封第一講書(shū)人閱讀 37,643評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤蝠咆,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后谈况,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,095評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡递胧,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,448評(píng)論 2 325
  • 正文 我和宋清朗相戀三年碑韵,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片缎脾。...
    茶點(diǎn)故事閱讀 38,566評(píng)論 1 339
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡祝闻,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出遗菠,到底是詐尸還是另有隱情联喘,我是刑警寧澤,帶...
    沈念sama閱讀 34,253評(píng)論 4 328
  • 正文 年R本政府宣布辙纬,位于F島的核電站豁遭,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏贺拣。R本人自食惡果不足惜蓖谢,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,829評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望譬涡。 院中可真熱鬧闪幽,春花似錦、人聲如沸涡匀。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,715評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)陨瘩。三九已至腕够,卻和暖如春级乍,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背燕少。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,945評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工卡者, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人客们。 一個(gè)月前我還...
    沈念sama閱讀 46,248評(píng)論 2 360
  • 正文 我出身青樓崇决,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親底挫。 傳聞我的和親對(duì)象是個(gè)殘疾皇子恒傻,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,440評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容

  • 1. 簡(jiǎn)介 1.1 什么是 MyBatis ? MyBatis 是支持定制化 SQL建邓、存儲(chǔ)過(guò)程以及高級(jí)映射的優(yōu)秀的...
    笨鳥(niǎo)慢飛閱讀 5,452評(píng)論 0 4
  • MyBatis 理論篇 [TOC] 什么是MyBatis ?MyBatis是支持普通SQL查詢,存儲(chǔ)過(guò)程和高級(jí)映射...
    有_味閱讀 2,887評(píng)論 0 26
  • 前言 主題是Mybatis一級(jí)和二級(jí)緩存的應(yīng)用及源碼分析盈厘。希望在本場(chǎng)chat結(jié)束后,能夠幫助讀者朋友明白以下三點(diǎn)官边。...
    余平的余_余平的平閱讀 1,321評(píng)論 0 12
  • 編寫(xiě)日志輸出環(huán)境配置文件 在開(kāi)發(fā)過(guò)程中沸手,最重要的就是在控制臺(tái)查看程序輸出的日志信息,在這里我們選擇使用 log4j...
    我沒(méi)有三顆心臟閱讀 6,527評(píng)論 0 33
  • Hello JianShu ! 好吧注簿,職業(yè)病又犯了契吉。看來(lái)我是一個(gè)真正的程序猿诡渴。感覺(jué)我們的Hello world是萬(wàn)...
    小強(qiáng)德美閱讀 250評(píng)論 1 0