Java——Mybatis一級緩存

一、概述

當用戶頻繁查詢某些固定的數據時,第一次將這些數據從數據庫中查詢出來,保存在緩存(內存,高速磁盤)中。當下次用戶再次查詢這些數據時,不用再通過數據庫查詢,而是去緩存裏面查詢

這麼做的目的,一是提升查詢速度,二是降低數據庫的併發請求壓力

在Mybatis中,緩存分爲兩種 : 一級緩存和二級緩存。而Mybatis默認開啓一級緩存。

一級緩存是SqlSession級別的,二級緩存是Mapper級別的。

 

二、一級緩存

我們的請求都是由SqlSession來執行的,確切的說,應該是由DefaultSqlSession來執行的,更確切的說,其實是由DefaultSqlSession的Executor執行器來執行的。

一級緩存是針對每一個sqlSession進行緩存。每個sqlSession對象中使用HashMap存儲一級緩存數據,key爲hashcode+statementId+sql語句。Value爲查詢出來的結果集映射成的java對象。

不同的sqlSession中的緩存是互相不能讀取的,即不共享。

 

三、生命週期

1.MyBatis在開啓一個數據庫會話時,會創建一個新的SqlSession對象,SqlSession對象持有一個Executor對象,
Executor對象持有一個PerpetualCache對象;

2.第一次查詢先去緩存中找是否有緩存數據,發現沒有,查詢數據庫,將查詢到的數據寫入sqlsession的一級緩存區域。 

3.第二次查詢先去緩存中找是否有緩存數據,發現有,直接從緩存區域中取出數據返回。 

4.當會話結束時,SqlSession對象及其內部的Executor對象還有PerpetualCache對象也一併釋放掉。

如果SqlSession調用了close()方法,會釋放掉一級緩存PerpetualCache對象,一級緩存將不可用。

SqlSession中執行了任何一個update操作(update()、delete()、insert()) ,都會調用clearCache(),清空PerpetualCache對象中的數據,但是該對象仍可使用。(保證數據有效性)

 

四、存在問題

1.一級緩存並沒有做粒度控制,而是在一次會話中對數據庫中所有表的sql操作均做了緩存,這顯然是不合理的。

2.任何更新(增、刪、改)操作都會清除一級緩存,其實在有些情況下,這完全沒有必要,比如兩個完全不相關的表1和表2,如果你更新了表1,那爲什麼也要把表2的緩存也清除?

3.即便更新操作置空了當前SqlSession的一級緩存,也只是能夠保證當前SqlSession的緩存失效,保證數據一致性,但是也不能保證其他SqlSession的緩存數據失效,這會導致數據不一致問題。

4.一級緩存只適用於單點,而不支持分佈式部署。

5.而一級緩存的設計是每個sqlsession單獨使用一個緩存空間,不同的sqlsession是不能互相訪問數據的。當然,在sqlsession關閉後,其中數據自然被清空。

6.一般在mybatis集成spring時,會把SqlSessionFactory設置爲單例注入到IOC容器中,不把sqlsession也設置爲單例的原因是sqlsession是線程不安全的,所以不能爲單例。那也就意味着其實是有關閉sqlsession的過程的。其實,對於每一個service中的sqlsession是不同的,這是通過mybatis-spring中的org.mybatis.spring.mapper.MapperScannerConfigurer創建sqlsession自動注入到service中的。 

特此警告!!!! 
當MyBatis與spring整合後,如果沒有事務,一級緩存是失效的!一級緩存是失效的!一級緩存是失效的! 
原因就是兩者結合後,sqlsession如果發現當前沒有事務,那麼每執行一個mapper方法,sqlsession就被關閉了。如果需要維持一級緩存的可用性,有兩種途徑:

1.添加事務

2.使用二級緩存

綜合以上一級緩存存在的問題,Mybatis設計開發了二級緩存,我們將在下一篇文章中介紹。

 

參考博客:

https://blog.csdn.net/u011403655/article/details/46696065

https://blog.csdn.net/liuzhixiong_521/article/details/85063689

https://blog.csdn.net/hd243608836/article/details/78654984

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章