mybatis 之緩存機制
1、緩存機制的簡單介紹:
a、MyBatis 包含一個非常強大的查詢緩存特性,它可以非常方便地配置和定制。緩存可以極大的提升查詢效率。
b、MyBatis 系統中默認定義了兩級緩存:
一級緩存和二級緩存:
- 默認情況下,只有一級緩存(SqlSession 級別的緩存,也稱為本地緩存)開啟。
- 二級緩存需要手動開啟和配置,它是基於 namespace 級別的緩存。
- 為了提高擴展性。MyBatis 定義了緩存接口 Cache。我們可以通過實現 Cache 接口來自定義二級緩存。
2、一級緩存:
a、一級緩存(local cache),即本地緩存,作用域默認是 sqlSession。一級緩存是一直開啟的,無法關閉;是 sqlSession 級別的一個 Map 。
與數據庫同一次會話期間查詢到的數據會放到本地緩存中。
以後如果需要獲取相同的數據,直接從緩存中拿,沒有必要再去查詢數據庫。
註:可以看到上圖的控制臺輸出結果,sql 語句只向數據庫發送了一條,在相同的會話下(同一個 SqlSession,相同的查詢條件),獲取到的是同一個對象。
b、一級緩存失效的四種情況:
- 不同的 SqlSession 對應不同的一級緩存
註:可以看到,發送了兩條 sql 語句,並且返回的 Employee 類的對象是兩個不同的對象。
- 同一個 SqlSession 但是查詢條件不同
- 同一個 SqlSession 兩次查詢期間執行了任何一次增刪改操作
- 同一個 SqlSession 兩次查詢期間手動清空了緩存
3、二級緩存:(全局緩存)基於 namespace 級別的緩存,一個 namespase 對應一個二級緩存:
a、工作機制:
- 一個會話,查詢一條數據,這個數據就會被放在當前會話的一級緩存中。
- 如果會話結束,一級緩存中的數據會被保存在二級緩存中;新的會話查詢信息,就可以參照二級緩存。
- 不同的 namsespace 查詢出的數據會放在自己對應的緩存中。(map)
b、實際出現的效果:
數據會從二級緩存中獲取。查出的數據都會默認先放在一級緩存中,只有會話提交或者關閉以後,一級緩存中的數據才會轉移到二級緩存中。
c、使用的方式:
- 開啟全局配置文件(我的文件名叫做 mybatis-config.xml)配置:<setting name="cacheEnabled" value="true"/>(手動配置,即使默認配置的屬性是 true,防止版本更新時帶來的問題)
- 在 mapper.xml sql 映射文件中配置 <cache></cache>使用二級緩存。(所以說是基於
namespace 的緩存)
cache 標簽中相關屬性的配置:
- eviction:緩存的回收策略
* LRU - 最近最少使用的,移除最長時間不被使用的對象(默認)
* FIFO - 先進先出:按對象進入緩存的順序來移除它們
* SOFT - 軟引用:移除基於垃圾回收器狀態和軟引用規則的對象
* WEAK - 弱引用:更積極地移除基於垃圾收集器狀態和弱引用規則的對象
- flushInterval:緩存刷新間隔
* 緩存多長時間清空一下,默認不清空,設置一個毫秒值
- readOnly:是否只讀
* true 只讀:mybatis 認為所有從緩存中獲取數據的操作都是只讀操作,不會修改數據。但是 mybatis 為了加快獲取速度,直接就會將數據在緩存中的引用交給用戶。(不安全,但速度快)
* false 非只讀:mybatis 認為獲取的數據可能被修改。mybatis 會利用序列化和反序列化的技術克隆一份新的數據給你。安全,但是速度慢。(默認設置,javabean 類需要實現 Serializable 接口)
- size:緩存中存放多少元素
- type="":指定自定義緩存的全類名。(實現 Cache 接口即可)
我們來看看示例的代碼:
註:做了相關設置後,測試代碼輸出結果顯示,只發送了一條 sql 語句,因為在 openSession 對象關閉後,mybatis 默認會先從二級緩存中取出數據。(因為底層是序列化和反序列化機制,所以返回的對象並不相同,但屬性相同)
在新的會話進入後,查詢數據會先到二級緩存中查找,後到一級緩存中查找,最後才是數據庫中查找。
本文出自 “12392717” 博客,請務必保留此出處http://12402717.blog.51cto.com/12392717/1932302
mybatis 之緩存機制