1. 程式人生 > >Mybatis一級快取、二級快取詳講

Mybatis一級快取、二級快取詳講

 

Mybatis 一級快取、二級快取

作者 : Stanley 羅昊

【轉載請註明出處和署名,謝謝!】

查詢快取

首先,我們先看一下這個標題“查詢快取”,那就說明跟增、刪、改是沒有任何關聯的,只有在查詢時,才會遇到快取,增刪改不涉及!

查詢快取目前Mybatis中提供了兩個,分別是:一級快取、二級快取;

一級快取

先說一下一級快取的範圍:同一個SqlSession物件,也就說,我們是同一個SqlSession物件,又要進行同樣的查詢操作,那麼,我們就可以去快取中獲取;

所以,SqlSession的快取,是屬於一級快取;

那,又有什麼用呢?

比如,我們現在資料庫中有兩條資料,分別是張三跟李四;

我現在呢,要根據name來查詢張三這個人,首先說明一點,這是第一次去根據name來查詢張三,這個時候呢,我們就會去訪問資料庫,去獲取name是張三的資料,拿到張三後,它會把張三又放進了Sqlssion物件中去了,Sqlssion物件存在記憶體中;

也就是說,我們第一次查完後,我們會將張三這個資料從資料庫中獲取一下,獲取後放到快取裡面,此時的快取就在記憶體裡面,具體的來說,它就在Sqlsession物件裡面;

上述操作如下圖:

 

如果,再有一次或再有N次來查詢這個張三,我就不需要去訪問資料庫了,因為我在快取裡面已經有了,如果你再要拿這個張三,直接直接從快取裡面去拿;

因此呢,我們可以發現,快取可以減少資料庫的訪問;

 

我們都知道,資料庫的開啟與關閉均比較費效能,所以,我們就不需要從資料庫中拿了,直接從快取中去獲取就完事了,意思就是可以提高效能;

SqlSession物件清空機制

只要執行你commit(提交)這個方法,那麼就會直接將SqlSession物件全部清空掉,一旦執行commit,就會清理我們的快取物件;

上述如下圖:

首先,這些操作,我們不需要去手動的去編寫,我們僅需知道並瞭解即可,因為Mybatis默認了就開啟了一級快取;

總結:

如果用相同的SqlSession物件查詢相同的資料,則只會在第一次查詢時傳送Sql語句,並將這個查詢的結果放入到Sqlsession中(作為快取存在);

後續再次查詢該同意的物件時,則直接從快取中查詢該物件即可(即省略了資料庫的訪問)

二級快取

首先,這個Mybatis自帶二級快取;

也有三方提供的二級快取;

Mybatis覺得快取很重要,所以就自帶了一個快取,但是,Mybatis必定不是搞快取的,搞資料的,但是第三方公司給你提供了一些快取,因為你mybatis做快取這塊兒不是專業的;

我們可以回顧一下,一級快取是同一個Sqlsession物件,那麼二級快取呢?

二級快取是同一個在同一個namespace生成的mapper物件,重點是這個namespace; 

也就是說,哪怕你生成了許多物件,只要你這個物件來自同一個namespace,它們就會共享同一個快取;

什麼是namespace,我在這裡就不強調了,因為這個是mybatis入門必學的;

簡單點來說:

只要產生的xxxMapper物件來自於同一個namespace,則,這個物件共享二級快取;

二級快取的這個共享範圍,是同一個namespace產生的xxxMapper物件;

開啟快取很簡單,如果你是boot專案的話,直接在你需要開啟的mapper.xml中加上一句話,來表示本namespace開啟了二級快取:

<cache/>;

如果是ssm框架的話,需要在conf.xml中新增一些配置:

在這裡,順便提一下,mybatis的二級快取是屬於序列化,序列化的意思就是從記憶體中的資料傳到硬碟中,這個過程就是序列化;

反序列化意思就是相反而已;

也就是說,mybatis的二級快取,實際上就是將資料放進了硬碟檔案中去了;

實現序列化介面

如果你要使用mybatis的二級快取,那麼你除了要在你需要快取的mappe.xml中開啟以外,你還需要實現序列化的介面,在你需要使用二級快取的實體類中;

去實現這個 Serializable(序列化)介面即可;

 現在呢,你僅僅的將Student類給序列化了,Student有父類、級聯屬性,它們是不會跟著被序列化的,所以光這些是不夠的;

其實很簡單,如果Student需要序列化,但是這個類中還有其他類的屬性,僅需將其他類也序列化即可!

比如學生類中繼承了父類,那麼父類也需要實現Serializable這個介面進行序列化;

快取時機

該序列化也序列化了,也已經在你需要進行快取的mapper.xml檔案中也開啟快取了,但是如果你使用原生的SqlsessionFacotry(SSM\SpringBoot除外因為是整合好的不需要寫底層)去寫的時候會發現,快取並沒有起效,而是關閉Session(session.close())才生效了;

這個其實就是mybatis的一個機制,其實很好理解;

比如,我現在去查詢張三,獲取張三資料之後我們需要經過序列化然後存貯到硬碟上,上面我也說過了,mybatis的二級快取實際上就是將資料儲存到硬碟上的某個檔案中了,照這樣,每來一個新的物件,比如張三存進來了,李四也需要存,王五也需要,如果是儲存到硬碟上,那麼就會用到IO技術,眾所周知,IO也是比較費效能,所以這個機制就是當你關閉session的時候,我們把這些張三、李四、王五這些資料一塊兒儲存到硬碟上,而不是來一個儲存一個這樣IO也受不了,所以就存在這樣的機制;