Mybatis緩存機制淺述

1.一級緩存

a.定義: mybatis一級緩存是指在內存中開闢一塊區域,用來保存用戶對資料庫的操作信息(sql)和資料庫返回的數據,如果下

一次用戶再執行相同的請求,那麼直接從內存中讀數數據而不是從資料庫讀取。

b.對sqlsession執行commit操作時

對sqlsession執行commit操作,也就意味著用戶執行了update、delete等操作,那麼資料庫中的數據勢必會發生變化,如

果用戶請求數據仍然使用之前內存中的數據,那麼將讀到臟數據。所以在執行sqlsession操作后,會清除保存數據的

HashMap,用戶在發起查詢請求時就會重新讀取數據並放入一級緩存中了。

c.關閉sqlsession

Advertisements

1. 一般在mybatis集成spring時,會把SqlSessionFactory設置為單例注入到IOC容器中,不把sqlsession也設置為單例的原

因是sqlsession是線程不安全的,所以不能為單例。那也就意味著其實是有關閉sqlsession的過程的。其實,對於每一

個service中的sqlsession是不同的,這是通過mybatis-spring中的

org.mybatis.spring.mapper.MapperScannerConfigurer創建sqlsession自動注入到service中的。

2. 而一級緩存的設計是每個sqlsession單獨使用一個緩存空間,不同的sqlsession是不能互相訪問數據的。當然,在

Advertisements

sqlsession關閉后,其中數據自然被清空

2.二級緩存

a.定義:關閉了sqlsession后的確把之前的緩存數據清空了,之後再執行同樣的查詢操作也會再訪問一遍資料庫。為了解決這個

需要使用二級緩存

b.作用域:一級緩存的作用域僅限於一個sqlsession,但是二級緩存的作用域是一個namespace。但並不是意味著同一個

namespace創建的mapper可以互相讀取緩存內容,這裡的原則是,如果開啟了二級緩存,那麼在關閉sqlsession后,會

把該sqlsession一級緩存中的數據添加到namespace的二級緩存中。

c.存儲:每一個namespace的mapper都有一個二緩存區域,兩個mapper的namespace如果相同,這兩個mapper執行sql查詢到數

據將存在相同的二級緩存區域中。

c.二級緩存的使用過程:

1.打開二級緩存總開關

打開總開關,只需要在mybatis總配置文件中加入一行設置

<settings>

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

<setting name="cacheEnabled" value="true"/>

</settings>

2.打開需要使用二級緩存的mapper的開關

在需要開啟二級緩存的mapper.xml中加入caceh標籤

<cache/>

3.POJO序列化:(Plain Ordinary Java Object)簡單的Java對象,實際就是普通JavaBeans,是為了避免和EJB混淆所

創造的簡稱。

讓需要使用二級緩存的POJO類實現Serializable介面,如

public class User implements Serializable {

d.二級緩存使用須知:1.即使開啟了二級緩存,不同的sqlsession之間的緩存數據也不是想互訪就能互訪的,必須等到

sqlsession關閉了以後,才會把其一級緩存中的數據寫入二級緩存。

2.在statement中設置useCache=false可以禁用當前select語句的二級緩存,即每次查詢都會發出sql去

查詢,默認情況是true,即該sql使用二級緩存。

<selectid='findOrderListResultMap' resultMap='ordersUserMap' useCache='false'>

總結:針對每次查詢都需要最新的數據sql,要設置成useCache=false,禁用二級緩存。

3.mybatis刷新緩存(就是清空緩存)

a.在mapper的同一個namespace中,如果有其它insert、update、delete操作數據后需要刷新緩存,如果

不執行刷新緩存會出現臟讀。

b.設置statement配置中的flushCache='true' 屬性,默認情況下為true即刷新緩存,如果改成false則

不會刷新。使用緩存時如果手動修改資料庫表中的查詢數據會出現臟讀。

如下:

<insertid='insertUser' parameterType='cn.itcast.mybatis.po.User' flushCache='true'>

總結:一般下執行完commit操作都需要刷新緩存,flushCache=true表示刷新緩存默認情況下為true,我

們不用去設置它,這樣可以避免資料庫臟讀。

f.Mybatis Cache參數

1.flushInterval(刷新間隔)可以被設置為任意的正整數,而且它們代表一個合理的毫秒形式的時間段。默認情況是

不設置,也就是沒有刷新間隔,緩存僅僅調用語句時刷新。

2.size(引用數目)可以被設置為任意正整數,要記住你緩存的對象數目和你運行環境的可用內存資源數目。默認值

是1024。

3.readOnly(只讀)屬性可以被設置為true或false。只讀的緩存會給所有調用者返回緩存對象的相同實例。因此這些

對象不能被修改。這提供了很重要的性能優勢。可讀寫的緩存會返回緩存對象的拷貝(通過序列化)。這會慢一些

,但是安全,因此默認是false

如下例子:

<cache eviction='FIFO' flushInterval='60000' size='512' readOnly='true'/>

這個更高級的配置創建了一個 FIFO 緩存,並每隔 60 秒刷新,存數結果對象或列表的 512 個引用,而且返回的

對象被認為是只讀的,因此在不同線程中的調用者之間修改它們會導致衝突。可用的收回策略有, 默認的是 LRU:

1. LRU – 最近最少使用的:移除最長時間不被使用的對象。

2. FIFO – 先進先出:按對象進入緩存的順序來移除它們。

3. SOFT – 軟引用:移除基於垃圾回收器狀態和軟引用規則的對象。

4. WEAK – 弱引用:更積極地移除基於垃圾收集器狀態和弱引用規則的對象。

2.緩存的作用:提供查詢緩存,用於減輕數據壓力,提高資料庫性能。

3.分散式緩存:ehcache是一個分散式緩存框架。

EhCache 是一個純Java的進程內緩存框架,是一種廣泛使用的開源Java分散式緩存,具有快速、精幹等特點,是

Hibernate中默認的CacheProvider。

4.緩存局限性:mybatis二級緩存對細粒度的數據級別的緩存實現不好,對同時緩存較多條數據的緩存,比如如下需求:對商品信息

進行緩存,由於商品信息查詢訪問量大,但是要求用戶每次都能查詢最新的商品信息,此時如果使用mybatis的二級

緩存就無法實現當一個商品變化時只刷新該商品的緩存信息而不刷新其它商品的信息,因為mybaits的二級緩存區域

以mapper為單位劃分,當一個商品信息變化會將所有商品信息的緩存數據全部清空。解決此類問題需要在業務層根據

需求對數據有針對性緩存。需要使用三級緩存

博客鏈接地址:http://www.360doc.com/content/15/1205/07/29475794_518018352.shtml

博客鏈接地址:http://www.mamicode.com/info-detail-890951.html

Advertisements

你可能會喜歡