mybatis有一級和二級緩存残家,一級是sqlSession級別,二級是application級別。
一級緩存的生命周期:
a. MyBatis在開啟一個數(shù)據(jù)庫會話時,會創(chuàng)建一個新的SqlSession對象,SqlSession對象中會有一個新的Executor(接口)颜凯,Executor對象中持有一個新的PerpetualCache對象彼城;當(dāng)會話結(jié)束時帜乞,SqlSession對象及其內(nèi)部的Executor對象還有PerpetualCache對象也一并釋放掉照棋。
b. 如果SqlSession調(diào)用了close()方法宝恶,會釋放掉一級緩存PerpetualCache對象丽蝎,一級緩存將不可用;
c. 如果SqlSession調(diào)用了clearCache()缸逃,會清空PerpetualCache對象中的數(shù)據(jù),但是該對象仍可使用乾蓬;
d.SqlSession中執(zhí)行了任何一個update操作(update()、delete()铜跑、insert()) 护锤,都會清空PerpetualCache對象的數(shù)據(jù)掩缓,但是該對象可以繼續(xù)使用宴凉;
一級緩存的工作流程:
一級緩存用的是HashMap弥锄,根據(jù)Key查詢數(shù)據(jù)罐盔,沒有就去數(shù)據(jù)庫查詢?nèi)缓蠓旁诰彺嬷小?/h5>
如何構(gòu)建這個Key是關(guān)鍵惶看,Cache接口的設(shè)計以及CacheKey的定義(非常重要)
將本次查詢使用的特征值作為key本今,將查詢結(jié)果作為value存儲到Map中逛艰。
現(xiàn)在最核心的問題出現(xiàn)了:怎樣來確定一次查詢的特征值丹诀?
換句話說就是:怎樣判斷某兩次查詢是完全相同的查詢衙伶?
也可以這樣說:如何確定Cache中的key值祈坠?
mybatis底層是jdbc,通過4個條件確定這個KEY矢劲。
- 傳入的 statementId
- 查詢時要求的結(jié)果集中的結(jié)果范圍 (結(jié)果的范圍通過rowBounds.offset和rowBounds.limit表示)赦拘;
- 這次查詢所產(chǎn)生的最終要傳遞給JDBC java.sql.Preparedstatement的Sql語句字符串(boundSql.getSql() )
- 傳遞給java.sql.Statement要設(shè)置的參數(shù)值
一級緩存的性能分析
1.MyBatis對會話(Session)級別的一級緩存設(shè)計的比較簡單,就簡單地使用了HashMap來維護(hù)芬沉,并沒有對HashMap的容量和大小進(jìn)行限制躺同。
讀者有可能就覺得不妥了:如果我一直使用某一個SqlSession對象查詢數(shù)據(jù),這樣會不會導(dǎo)致HashMap太大丸逸,而導(dǎo)致 java.lang.OutOfMemoryError錯誤疤R铡? 讀者這么考慮也不無道理黄刚,不過MyBatis的確是這樣設(shè)計的捎谨。
MyBatis這樣設(shè)計也有它自己的理由:
a. 一般而言SqlSession的生存時間很短。一般情況下使用一個SqlSession對象執(zhí)行的操作不會太多憔维,執(zhí)行完就會消亡侍芝;
b. 對于某一個SqlSession對象而言,只要執(zhí)行update操作(update埋同、insert州叠、delete),都會將這個SqlSession對象中對應(yīng)的一級緩存清空掉凶赁,所以一般情況下不會出現(xiàn)緩存過大咧栗,影響JVM內(nèi)存空間的問題;
c. 可以手動地釋放掉SqlSession對象中的緩存虱肄。
- 一級緩存是一個粗粒度的緩存致板,沒有更新緩存和緩存過期的概念
MyBatis的一級緩存就是使用了簡單的HashMap,MyBatis只負(fù)責(zé)將查詢數(shù)據(jù)庫的結(jié)果存儲到緩存中去咏窿, 不會去判斷緩存存放的時間是否過長斟或、是否過期,因此也就沒有對緩存的結(jié)果進(jìn)行更新這一說了集嵌。
根據(jù)一級緩存的特性萝挤,在使用的過程中御毅,我認(rèn)為應(yīng)該注意:
1、對于數(shù)據(jù)變化頻率很大怜珍,并且需要高時效準(zhǔn)確性的數(shù)據(jù)要求端蛆,我們使用SqlSession查詢的時候,要控制好SqlSession的生存時間酥泛,SqlSession的生存時間越長今豆,它其中緩存的數(shù)據(jù)有可能就越舊,從而造成和真實數(shù)據(jù)庫的誤差柔袁;同時對于這種情況呆躲,用戶也可以手動地適時清空SqlSession中的緩存;
2捶索、對于只執(zhí)行歼秽、并且頻繁執(zhí)行大范圍的select操作的SqlSession對象,SqlSession對象的生存時間不應(yīng)過長情组。