Mybatis中一級緩存、二級緩存的示例分析-創(chuàng)新互聯(lián)

這篇文章主要介紹了Mybatis中一級緩存、二級緩存的示例分析,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。

創(chuàng)新互聯(lián)建站自2013年起,先為貴溪等服務(wù)建站,貴溪等地企業(yè),進(jìn)行企業(yè)商務(wù)咨詢服務(wù)。為貴溪企業(yè)網(wǎng)站制作PC+手機(jī)+微官網(wǎng)三網(wǎng)同步一站式服務(wù)解決您的所有建站問題。

Mybatis 為我們提供了一級緩存和二級緩存,可以通過下圖來理解:

Mybatis中一級緩存、二級緩存的示例分析

①、一級緩存是SqlSession級別的緩存。在操作數(shù)據(jù)庫時需要構(gòu)造sqlSession對象,在對象中有一個數(shù)據(jù)結(jié)構(gòu)(HashMap)用于存儲緩存數(shù)據(jù)。不同的sqlSession之間的緩存數(shù)據(jù)區(qū)域(HashMap)是互相不影響的。

②、二級緩存是mapper級別的緩存,多個SqlSession去操作同一個Mapper的sql語句,多個SqlSession可以共用二級緩存,二級緩存是跨SqlSession的。

1、一級緩存

①、我們在一個 sqlSession 中,對 User 表根據(jù)id進(jìn)行兩次查詢,查看他們發(fā)出sql語句的情況。
@Test
public void testSelectOrderAndUserByOrderId(){
	//根據(jù) sqlSessionFactory 產(chǎn)生 session
	SqlSession sqlSession = sessionFactory.openSession();
	String statement = "one.to.one.mapper.OrdersMapper.selectOrderAndUserByOrderID";
	UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
	//第一次查詢,發(fā)出sql語句,并將查詢的結(jié)果放入緩存中
	User u1 = userMapper.selectUserByUserId(1);
	System.out.println(u1);
	
	//第二次查詢,由于是同一個sqlSession,會在緩存中查找查詢結(jié)果
	//如果有,則直接從緩存中取出來,不和數(shù)據(jù)庫進(jìn)行交互
	User u2 = userMapper.selectUserByUserId(1);
	System.out.println(u2);
	
	sqlSession.close();
}

查看控制臺打印情況:

Mybatis中一級緩存、二級緩存的示例分析

②、 同樣是對user表進(jìn)行兩次查詢,只不過兩次查詢之間進(jìn)行了一次update操作。
@Test
public void testSelectOrderAndUserByOrderId(){
	//根據(jù) sqlSessionFactory 產(chǎn)生 session
	SqlSession sqlSession = sessionFactory.openSession();
	String statement = "one.to.one.mapper.OrdersMapper.selectOrderAndUserByOrderID";
	UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
	//第一次查詢,發(fā)出sql語句,并將查詢的結(jié)果放入緩存中
	User u1 = userMapper.selectUserByUserId(1);
	System.out.println(u1);
	
	//第二步進(jìn)行了一次更新操作,sqlSession.commit()
	u1.setSex("女");
	userMapper.updateUserByUserId(u1);
	sqlSession.commit();
	
	//第二次查詢,由于是同一個sqlSession.commit(),會清空緩存信息
	//則此次查詢也會發(fā)出 sql 語句
	User u2 = userMapper.selectUserByUserId(1);
	System.out.println(u2);
	
	sqlSession.close();
}

控制臺打印情況:

Mybatis中一級緩存、二級緩存的示例分析

③、總結(jié)

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

2、如果中間sqlSession去執(zhí)行commit操作(執(zhí)行插入、更新、刪除),則會清空SqlSession中的一級緩存,這樣做的目的為了讓緩存中存儲的是最新的信息,避免臟讀。

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

Mybatis中一級緩存、二級緩存的示例分析

2、二級緩存

二級緩存的原理和一級緩存原理一樣,第一次查詢,會將數(shù)據(jù)放入緩存中,然后第二次查詢則會直接去緩存中取。但是一級緩存是基于 sqlSession 的,而 二級緩存是基于 mapper文件的namespace的,也就是說多個sqlSession可以共享一個mapper中的二級緩存區(qū)域,并且如果兩個mapper的namespace相同,即使是兩個mapper,那么這兩個mapper中執(zhí)行sql查詢到的數(shù)據(jù)也將存在相同的二級緩存區(qū)域中。

Mybatis中一級緩存、二級緩存的示例分析

那么二級緩存是如何使用的呢?

①、開啟二級緩存

和一級緩存默認(rèn)開啟不一樣,二級緩存需要我們手動開啟

首先在全局配置文件 mybatis-configuration.xml 文件中加入如下代碼:

<!--開啟二級緩存  -->
<settings>
	<setting name="cacheEnabled" value="true"/>
</settings>

其次在 UserMapper.xml 文件中開啟緩存

<!-- 開啟二級緩存 -->
<cache></cache>

我們可以看到 mapper.xml 文件中就這么一個空標(biāo)簽<cache/>,其實(shí)這里可以配置<cache type="org.apache.ibatis.cache.impl.PerpetualCache"/>,PerpetualCache這個類是mybatis默認(rèn)實(shí)現(xiàn)緩存功能的類。我們不寫type就使用mybatis默認(rèn)的緩存,也可以去實(shí)現(xiàn) Cache 接口來自定義緩存。

Mybatis中一級緩存、二級緩存的示例分析

Mybatis中一級緩存、二級緩存的示例分析

我們可以看到 二級緩存 底層還是 HashMap 架構(gòu)。

②、po 類實(shí)現(xiàn)  Serializable  序列化接口

Mybatis中一級緩存、二級緩存的示例分析

開啟了二級緩存后,還需要將要緩存的pojo實(shí)現(xiàn)Serializable接口,為了將緩存數(shù)據(jù)取出執(zhí)行反序列化操作,因?yàn)槎壘彺鏀?shù)據(jù)存儲介質(zhì)多種多樣,不一定只存在內(nèi)存中,有可能存在硬盤中,如果我們要再取這個緩存的話,就需要反序列化了。所以mybatis中的pojo都去實(shí)現(xiàn)Serializable接口。

③、測試

一、測試二級緩存和sqlSession 無關(guān)

@Test
public void testTwoCache(){
	//根據(jù) sqlSessionFactory 產(chǎn)生 session
	SqlSession sqlSession1 = sessionFactory.openSession();
	SqlSession sqlSession2 = sessionFactory.openSession();
	
	String statement = "com.ys.twocache.UserMapper.selectUserByUserId";
	UserMapper userMapper1 = sqlSession1.getMapper(UserMapper.class);
	UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class);
	//第一次查詢,發(fā)出sql語句,并將查詢的結(jié)果放入緩存中
	User u1 = userMapper1.selectUserByUserId(1);
	System.out.println(u1);
	sqlSession1.close();//第一次查詢完后關(guān)閉sqlSession
	
	//第二次查詢,即使sqlSession1已經(jīng)關(guān)閉了,這次查詢依然不發(fā)出sql語句
	User u2 = userMapper2.selectUserByUserId(1);
	System.out.println(u2);
	sqlSession2.close();
}

可以看出上面兩個不同的sqlSession,第一個關(guān)閉了,第二次查詢依然不發(fā)出sql查詢語句。

二、測試執(zhí)行 commit() 操作,二級緩存數(shù)據(jù)清空

@Test
public void testTwoCache(){
	//根據(jù) sqlSessionFactory 產(chǎn)生 session
	SqlSession sqlSession1 = sessionFactory.openSession();
	SqlSession sqlSession2 = sessionFactory.openSession();
	SqlSession sqlSession3 = sessionFactory.openSession();
	
	String statement = "com.ys.twocache.UserMapper.selectUserByUserId";
	UserMapper userMapper1 = sqlSession1.getMapper(UserMapper.class);
	UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class);
	UserMapper userMapper3 = sqlSession2.getMapper(UserMapper.class);
	//第一次查詢,發(fā)出sql語句,并將查詢的結(jié)果放入緩存中
	User u1 = userMapper1.selectUserByUserId(1);
	System.out.println(u1);
	sqlSession1.close();//第一次查詢完后關(guān)閉sqlSession
	
	//執(zhí)行更新操作,commit()
	u1.setUsername("aaa");
	userMapper3.updateUserByUserId(u1);
	sqlSession3.commit();
	
	//第二次查詢,由于上次更新操作,緩存數(shù)據(jù)已經(jīng)清空(防止數(shù)據(jù)臟讀),這里必須再次發(fā)出sql語句
	User u2 = userMapper2.selectUserByUserId(1);
	System.out.println(u2);
	sqlSession2.close();
}

查看控制臺情況:

Mybatis中一級緩存、二級緩存的示例分析

④、useCache和flushCache

mybatis中還可以配置userCache和flushCache等配置項(xiàng),userCache是用來設(shè)置是否禁用二級緩存的,在statement中設(shè)置useCache=false可以禁用當(dāng)前select語句的二級緩存,即每次查詢都會發(fā)出sql去查詢,默認(rèn)情況是true,即該sql使用二級緩存。

<select id="selectUserByUserId" useCache="false" resultType="com.ys.twocache.User" parameterType="int">
	select * from user where id=#{id}
</select>

這種情況是針對每次查詢都需要最新的數(shù)據(jù)sql,要設(shè)置成useCache=false,禁用二級緩存,直接從數(shù)據(jù)庫中獲取。

在mapper的同一個namespace中,如果有其它insert、update、delete操作數(shù)據(jù)后需要刷新緩存,如果不執(zhí)行刷新緩存會出現(xiàn)臟讀。

設(shè)置statement配置中的flushCache=”true” 屬性,默認(rèn)情況下為true,即刷新緩存,如果改成false則不會刷新。使用緩存時如果手動修改數(shù)據(jù)庫表中的查詢數(shù)據(jù)會出現(xiàn)臟讀。

<select id="selectUserByUserId" flushCache="true" useCache="false" resultType="com.ys.twocache.User" parameterType="int">
	select * from user where id=#{id}
</select>

一般下執(zhí)行完commit操作都需要刷新緩存,flushCache=true表示刷新緩存,這樣可以避免數(shù)據(jù)庫臟讀。所以我們不用設(shè)置,默認(rèn)即可。

感謝你能夠認(rèn)真閱讀完這篇文章,希望小編分享的“Mybatis中一級緩存、二級緩存的示例分析”這篇文章對大家有幫助,同時也希望大家多多支持創(chuàng)新互聯(lián),關(guān)注創(chuàng)新互聯(lián)-成都網(wǎng)站建設(shè)公司行業(yè)資訊頻道,更多相關(guān)知識等著你來學(xué)習(xí)!

分享題目:Mybatis中一級緩存、二級緩存的示例分析-創(chuàng)新互聯(lián)
文章出自:http://www.muchs.cn/article6/hgsog.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站改版小程序開發(fā)、網(wǎng)站排名電子商務(wù)、服務(wù)器托管企業(yè)網(wǎng)站制作

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

網(wǎng)站優(yōu)化排名