Spring+SpringMVC+MyBatis深入學習及搭建(八)——MyBatis查詢快取,springmvcmybatis
轉載請註明出處:http://www.cnblogs.com/Joanna-Yan/p/6956206.html
前面講到:Spring+SpringMVC+MyBatis深入學習及搭建(七)——MyBatis消極式載入
1.什麼是查詢快取
mybatis提供查詢快取,用於減輕資料庫壓力,提高資料庫效能。
mybatis提供一級緩衝和二級緩衝。
一級緩衝是SqlSession層級的緩衝。在操作資料庫時需要構造sqlSession對象,在對象中有一個資料結構(HashMap)用於儲存快取資料。不同的sqlSession之間的快取資料地區(HashMap)是互相不影響的。
二級緩衝是mapper層級的緩衝,多個sqlSession去操作同一個Mapper的sql語句,多個sqlSession可以共用二級緩衝,二級緩衝是跨sqlSession的。
為什麼要用緩衝?
如果緩衝中有資料就不用從資料庫中擷取,大大提高系統效能。
2.一級緩衝2.1一級緩衝工作原理
第一次發起查詢使用者id為1的使用者資訊,先去找緩衝中是否有id為1的使用者資訊,如果沒有,從資料庫查詢使用者資訊。
得到使用者資訊,將使用者資訊儲存到一級緩衝中。
如果sqlSession去執行commit操作(執行插入、更新、刪除),清空sqlSession中的一級緩衝,這樣做的目的為了讓緩衝中儲存的是最新的資訊,避免髒讀。
第二次發去查詢使用者id為1的使用者資訊,先去找緩衝中是否有id為1的使用者資訊,緩衝中有,直接從緩衝中擷取使用者資訊。
2.2一級緩衝測試
mybatis預設支援一級緩衝,不需要在設定檔去配置。
按照上邊一級緩衝原理步驟去測試。
@Test public void testCache1() throws Exception{ SqlSession sqlSession=sqlSessionFactory.openSession(); UserMapper userMapper=sqlSession.getMapper(UserMapper.class); //下邊查詢使用一個SqlSession //第一次發起請求,查詢id為1的使用者 User user1=userMapper.findUserById(1); System.out.println(user1); //如果sqlSession去執行commit操作(執行插入、更新、刪除),清空sqlSession中的一級緩衝, //這樣做的目的是為了讓緩衝中儲存的是最新的資訊,避免髒讀。 //更新user1的資訊 user1.setUsername("測試使用者22"); userMapper.updateUser(user1); //執行commit操作去清空緩衝 sqlSession.commit(); //第二次發起請求,查詢id為1的使用者 User user2=userMapper.findUserById(1); System.out.println(user2); sqlSession.close(); }2.3一級緩衝應用
正式開發,是將mybatis和spring進行整合開發,事務控制在service中。
一個service方法中包括很多Mapper方法調用。
service{
//開始執行時,開啟事務,建立SqlSession對象
//第一次調用mapper的方法findUserById(1)
//第二次調用mapper的方法findUserById(1),從一級緩衝中取資料
//方法結束,sqlSession關閉
}
如果是執行兩次service調用查詢相同的使用者資訊,不走一級緩衝,因為session方法結束,sqlSession就關閉,一級緩衝就清空。
3.二級緩衝3.1二級緩衝原理
首先開啟mybatis的二級緩衝。
sqlSession1去查詢使用者id為1的使用者資訊,查詢到使用者資訊後悔講查詢資料存放區到二級緩衝中。
如果sqlSession3去執行相同mapper下的sql,執行commit提交,會清空該mapper下的二級快取區域的資料。
sqlSession2去查詢使用者id為1的使用者資訊,去緩衝中找是否存在資料,如果存在直接從緩衝中取出資料。
二級緩衝與一級緩衝區別:二級緩衝的範圍更大,多個sqlSession可以共用一個UserMapper的二級快取區域。UserMapper有一個二級快取區域(按namespace分),其它mapper也有自己的二級快取區域(按namespace分)。
每個namespace的mapper都有一個二級快取區域,兩個mapper的namespace如果相同,這兩個mapper執行sql查詢到的資料將存在相同的二級快取區域中。
3.2開啟二級緩衝
mybatis的二級緩衝是mapper範圍層級,除了在SqlMapConfig.xml設定二級緩衝的總開關,還要在具體的mapper.xml中開啟二級緩衝。
在核心設定檔SqlMapConfig.xml中加入:
<setting name="cacheEnabled" value="true"/>
| |
描述 |
允許值 |
預設值 |
|
cacheEnabled |
對在此設定檔下的所有cache 進行全域性開/關設定。 |
true false |
true |
在UserMapper.xml中開啟二級緩衝,UserMapper.xml下的sql執行完成後儲存在它的快取區域(HashMap)。
3.3調用pojo類實現序列化介面
為了將快取資料取出執行反序列劃操作,因為二級快取資料儲存介質多種多樣,不一定在記憶體。可能在硬碟、遠程等。
3.4測試方法
@Test public void testCache2() throws Exception{ SqlSession sqlSession1=sqlSessionFactory.openSession(); SqlSession sqlSession2=sqlSessionFactory.openSession(); SqlSession sqlSession3=sqlSessionFactory.openSession(); UserMapper userMapper1=sqlSession1.getMapper(UserMapper.class); UserMapper userMapper2=sqlSession2.getMapper(UserMapper.class); UserMapper userMapper3=sqlSession3.getMapper(UserMapper.class); //第一次發起請求,查詢id為1的使用者 User user1=userMapper1.findUserById(1); System.out.println(user1); //這裡執行關閉操作,將sqlSession中的資料寫到二級快取區域 sqlSession1.close(); //使用sqlSession3執行commit()操作 User user=userMapper3.findUserById(1); user1.setUsername("Joanna"); userMapper3.updateUser(user); //執行提交,清空UserMapper下邊的二級緩衝 sqlSession3.commit(); sqlSession3.close(); //第二次發起請求,查詢id為1的使用者 User user2=userMapper2.findUserById(1); System.out.println(user2); sqlSession2.close(); }3.5禁用二級緩衝
在statement中設定useCache=false可以禁用當前select語句的二級緩衝,即每次查詢都會發出sql,預設情況是true,即該sql使用二級緩衝。
<select id="findOrderListResultMap" resultMap="ordersUserMap" useCache="false">
3.6重新整理緩衝(就是清空緩衝)
在mapper的同一個namespace中,如果有其它insert、update、delete操作資料後需要重新整理緩衝,如果不執行重新整理緩衝會出現髒讀。
設定statement配置中的flushCache="true"屬性,預設情況下為true即重新整理緩衝,如果改成false則不會重新整理。使用緩衝時如果手動修改資料庫表中的查詢資料會出現髒讀。
<insert id="insertUser" parameterType="cn.itcast.mybatis.po.User" flushCache="true">
總結:一般情況下執行完commit操作都需要重新整理緩衝,flushCache=true表示重新整理緩衝,這樣可以避免資料庫髒讀。
3.7 Mybatis Cache參數
flushInterval(重新整理間隔)可以被設定為任意的正整數,而且它們代表一個合理的毫秒形式的時間端。預設情況是不設定,也局勢沒有重新整理間隔,緩衝僅僅調用語句時重新整理。
size(引用數目)可以被設定為任意正整數,要記住你緩衝的對象數目和你運行環境的可用記憶體資源數目。預設值是1024。
readOnly(唯讀)屬性可以被設定為true或false。唯讀緩衝會給所有調用者返回緩衝對象的相同執行個體。因此這些對象不能被修改。這提供了很重要的效能優勢。可讀寫的緩衝會返回緩衝對象的拷貝(通過序列化)。這會慢一些,但是安全,因此預設是false。
如下例子:
<cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true"/>
這個更進階的配置建立了一個 FIFO 緩衝,並每隔 60 秒重新整理,存數結果對象或列表的 512 個引用,而且返回的對象被認為是唯讀,因此在不同線程中的調用者之間修改它們會導致衝突。可用的收回策略有, 預設的是 LRU:
4.mybatis整合ehcache
ehcache是一個純Java的進程內緩衝架構,是一種廣泛使用的開源Java分布式緩衝,具有快速、精乾等特點,是Hibernate中預設的CacheProvider。
4.1分布式緩衝
為了提高系統並發、效能,一般會系統進行分布式部署(叢集部署方式)
不使用分布式緩衝,緩衝的資料在各個服務單獨儲存,不方便系統開發。所以要使用分布式緩衝對快取資料進行集中管理。
mybatis的特長是sql操作,快取資料的管理不是mybatis的特長。mybatis無法實現分布式緩衝,需要和其它分布式緩衝架構進行整合,如:redis、memcached、ehcache等。
4.2整合方法(掌握)
mybatis提供了一個cache介面,如果要實現自己的緩衝邏輯,實現cache介面開發即可。
mybatis和ehcache整合,mybatis和ehcache整合包中提供了一個cache介面的實作類別。
mybatis預設的cache實作類別是:
4.3加入ehcache包
4.4整合ehcache
配置mapper中cache中的type為ehcache對cache介面的實作類別型。
4.5加入ehcache的設定檔
在classpath下配置ehcache.xml
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../config/ehcache.xsd"> <diskStore path="F:\develop\ehcache" /> <defaultCache maxElementsInMemory="1000" maxElementsOnDisk="10000000" eternal="false" overflowToDisk="false" timeToIdleSeconds="120" timeToLiveSeconds="120" diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LRU"> </defaultCache></ehcache>
屬性說明:
diskStore:指定資料在磁碟中的儲存位置。
defaultCache:當藉助CacheManager.add(“demoCache”)建立Cache時,EhCache便會採用<defaultCache/>指定的管理原則。
以下屬性是必須的:
maxElementsInMemory :在記憶體中緩衝的element的最大數目。
maxElementsOnDisk :在磁碟上緩衝的element的最大數目,若是0表示無窮大。
eternal :設定緩衝的elements是否永遠不到期。如果為true,則緩衝的資料始終有效,如果為false,你們還要根據timeToIdleSeconds、timeToLiveSeconds判讀。
overflowToDisk :設定當記憶體緩衝溢出的時候是否將到期的element緩衝到磁碟上。
以下屬性是可選的:
timeToIdleSeconds :當緩衝在EhCache中的資料前後兩次訪問的時間超過timeToIdleSeconds的屬性取值時,這些資料便會刪除,預設值是0,也就是可閑置時間無窮大。
timeToLiveSeconds :緩衝element的有效生命期,預設是0,也就是element存活時間無窮大。
diskSpoolBufferSizeMB :這個參數設定DiskStore(磁碟緩衝)的緩衝區大小。預設是30MB,每個Cache都應該有自己的一個緩衝區。
diskPersistent :在VM重啟的時候是否啟用磁碟儲存EhCache中的資料,預設是false。
diskExpiryThreadIntervalSeconds - 磁碟緩衝的清理線程運行間隔,預設是120秒。每個120s,相應的線程會進行一次EhCache中資料的清理工作。
memoryStoreEvictionPolicy - 當記憶體緩衝達到最大,有新的element加入的時候, 移除緩衝中element的策略。預設是LRU(最近最少使用),可選的有LFU(最不常使用)和FIFO(先進先出)。
4.6測試程式
同3.4
4.7二級緩衝應用情境
對訪問多的查詢請求且使用者對查詢結果即時性要求不高,此時可採用mybatis二級緩衝技術降低資料庫訪問量,提高訪問速度,業務情境比如:耗時較高的統計分析sql、電話賬單查詢sql等。
實現方法如下:通過設定重新整理間隔時間,由mybatis每隔一段時間自動清空緩衝,根據資料變化頻率設定緩衝重新整理間隔flushInterval,比如設定為30分鐘、60分鐘、24小時等,根據需求而定。
4.8二級緩衝局限性
mybatis二級緩衝對細粒度的資料層級的緩衝實現不好,比如如下需求:對商品資訊進行緩衝,由於商品資訊查詢訪問量大,但是要求使用者每次都能查詢最新的商品資訊,此時如果使用mybatis的二級緩衝就無法實現當一個商品變化時只重新整理該商品的緩衝資訊而不重新整理其它商品的資訊,因為mybatis的二級快取區域以mapper為單位劃分,當一個商品資訊變化會將所有商品資訊的快取資料全部清空。解決此類問題需要再業務層根據需求對資料有針對性緩衝。
如果此文對您有協助,打賞我一下吧~