分享知識-快樂自己:Mybatis快取機制
阿新 • • 發佈:2018-11-11
論快取機制:
1):mybatis 提供了快取機制減輕資料庫壓力,提高資料庫效能。 2):mybatis 的快取分為兩級:一級快取、二級快取 3):一級快取是SqlSession級別的快取,快取的資料只在SqlSession內有效。 4):二級快取是mapper級別的快取,同一個namespace公用這一個快取,所以對 SqlSession是共享的一級快取:
mybatis 的一級快取是SqlSession級別的快取,在操作資料庫的時候需要先建立SqlSession會話物件,在物件中有一個HashMap用於儲存快取資料,此HashMap是當前會話物件私有的,別的SqlSession會話物件無法訪問。
具體流程:
1).第一次執行select完畢會將查到的資料寫入SqlSession內的HashMap中快取起來
2).第二次執行select會從快取中查資料,如果select相同切傳引數一樣,那麼就能從快取中返回資料,不用去資料庫了,從而提高了效率 注意事項: 1):一級快取的作用域是SqlSession範圍的,當在同一個SqlSession中執行兩次相同的 sql 語句時,第一次執行完畢會將資料庫中查詢的資料寫到快取(記憶體)中, 第二次查詢時會從快取中獲取資料,不再去底層進行資料庫查詢,從而提高了查詢效率。需要注意的是:如果SqlSession執行了DML操作(insert、update、delete),
二級快取:
二級快取是mapper級別的快取,也就是同一個namespace的mappe.xml,當多個SqlSession使用同一個Mapper操作資料庫的時候,得到的資料會快取在同一個二級快取區域,二級快取預設是沒有開啟的。
需要在setting全域性引數中配置開啟二級快取
conf.xml:
<settings>
<setting name="cacheEnabled" value="true"/>預設是false:關閉二級快取
<settings>
在userMapper.xml中配置:
<!--在當前內部Mapper中開啟二級快取--> <cache eviction="LRU" flushInterval="60000" size="512" readOnly="true"/> <!--引用全域性快取配置檔案--> <cache type="org.mybatis.caches.ehcache.LoggingEhcache"/>當前 mapper下所有語句開啟二級快取 這裡配置了一個LRU快取,並每隔60秒重新整理,最大儲存512個物件,而卻返回的物件是隻讀的。 cache元素用來開啟當前mapper的namespace下的二級快取,該元素的屬性設定如下: flushInterval: 重新整理間隔,可以被設定為任意的正整數,而且它們代表一個合理的毫秒形式的時間段,預設情況下是不設定的,也就是沒有重新整理間隔,快取僅僅呼叫語句時重新整理。 size: 快取數目,可以被設定為任意正整數,要記住你的快取物件數目和你執行環境可用記憶體資源數目,預設值是1024. readOnly: 只讀,屬性可以被設定為true或false,只讀的快取會給所有呼叫者返回快取物件的相同例項,因此這些物件不能被修改。 這提供了很重要的效能優勢,可讀寫的快取會返回快取物件的拷貝(通過序列化),這會慢一些,但是安全,因此預設是false。 eviction:收回策略,預設為LRU,有如下幾種: LRU:最近最少使用的策略,移除最長時間不被使用的物件。 FIFO:先進先出策略,按物件進入快取的順序來移除它們。 SOFT:軟引用策略,移除基於垃圾回收器狀態和軟引用規則的物件。 WEAK:弱引用策略,更積極地移除基於垃圾收集器狀態和弱引用規則的物件。 若想禁用當前select語句的二級快取,新增useCache="false"修改如下:
<select id="getCountByName" parameterType="java.util.Map"
resultType="INTEGER" statementType="CALLABLE" useCache="false">
具體流程:
1).當一個sqlseesion執行了一次select後,在關閉此session的時候,會將查詢結果快取到二級快取
2).當另一個sqlsession執行select時,首先會在他自己的一級快取中找,如果沒找到,就回去二級快取中找,找到了就返回,就不用去資料庫了,從而減少了資料庫壓力提高了效能。
注意事項一:
1).如果SqlSession執行了DML操作(insert、update、delete),並commit了,那麼
mybatis就會清空當前mapper快取中的所有快取資料,這樣可以保證快取中的存的數
據永遠和資料庫中一致,避免出現髒讀
2).mybatis的快取是基於[namespace:sql語句:引數]來進行快取的,意思就是SqlSession
的HashMap儲存快取資料時,是使用[namespace:sql:引數]作為key,查詢返回的語
句作為value儲存的。
注意事項二:
1):使用二級快取時,與查詢結果對映的java物件必須實現java.io.Serializable介面的序
列化和反序列化操作,如果存在父類,其成員都需要實現序列化介面,
實現序列化
介面是為了對快取資料進行序列化和反序列化操作,因為二級快取資料儲存介質多
種多樣,不一定在記憶體,有可能是硬碟或者遠端伺服器。
例:-1242243203:1146242777:winclpt.bean.userMapper.getUser:0:2147483647:select * from user where id=?:19
全域性配置檔案:
ehcache.xml:
<ehcache> <!--臨時檔案目錄 可以自己設定--> <diskStore path="java.io.tmpdir"/> <!-- maxElementsInMemory:在記憶體中最大的儲存量 eternal:是否在記憶體中永遠不銷燬 timeToIdleSeconds:在快取中閒置多少時間之後銷燬,預設單位是S timeToLiveSeconds:在快取中存活多少時間之後銷燬,無論是否有人使用,預設單位是S overflowToDisk:當快取滿的時候是否儲存到磁碟中 diskPersistent:磁碟中的檔案是否永久儲存 diskExpiryThreadIntervalSeconds:檢測執行緒執行時間間隔!預設單位是S ******************************************************* memoryStoreEvictionPolicy : 快取清理策略 1.LRU (least recently used) 最近最少使用 每個快取的元素都有一個時間戳,當快取容量滿的時候,需要騰出來新位置給新快取元素, 這時候,會比較時間戳然後刪除符合條件的快取元素 2.LFU (least frequently used )最少使用 一直以來最少使用的快取元素,快取元素中有一個hit值,hit值最少的將會清除! 3.FIFO(first in first out) 先進先出 --> <defaultCache maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="120" timeToLiveSeconds="120" overflowToDisk="true" diskPersistent="false" diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LRU" /> </ehcache>
參考:
1): https://blog.csdn.net/zouxucong/article/details/68947052
2): https://www.cnblogs.com/winclpt/articles/7511672.html
demo:
https://note.youdao.com/share/?id=80eda2335aa3c7605116c24ac6e03b48&type=note#/
END:
對於MyBatis 快取的內容僅做了解即可,因為面對一定規模的資料量,內建的Cache 方式就派不上用場了;並且對查詢結果集做快取並不是MyBatis 框架擅長的,它專心做的應該是SQL 對映。 所以採用 OSCache 、Memcached 等專門的快取伺服器來做更為合理。