mybatis高階知識(四)&查詢快取
阿新 • • 發佈:2019-02-14
1.查詢快取
1.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預設支援一級快取,不需要在配置檔案去配置 按照上邊一級快取原理步驟測試
測試程式碼
public testCacher1() throws Exception{
SqlSession sqlSesssion=sqlSessionFactory.openSession();//建立代理物件
UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
//下邊查詢使用一個SqlSession
//第一次發起請求,查詢id為1的使用者
User uyser=userMapper.findUserById (1);
System.out.println(:user1);
//如果SQLSession去執行commit操作(執行插入,更新,刪除) 清空SQLSession中的一級快取
這樣做的目的是為了讓快取中儲存的是最新的資訊,避main髒讀
//更新user的資訊
user.setUsername(“測試使用者22”);
userMapper.updateUser(user1);
//執行commint操作去清除快取
SQLSession.commit();
//第二次發起請求,查詢id為1的使用者
User user2=username.fiondUserById(1);
System.out.println(user2);
sqlSession.close();
}
2.3一級快取的應用
正式開發,是將mybatis和spring進行整合開發,事務空載子service中
一個service方法中包括很多mapper方法呼叫
service
//開始執行執行時,開啟事務,建立SQLSession物件
//第一呼叫mapper的方法findUserByID(1);
//第二次呼叫mapper的方法findUserByID(1);從一級快取中取資料
//方法結束sqlSession關閉
如果是倆次service呼叫查詢相同的使用者資訊,不走一級快取,因為service方法結束,SQLSession就關閉
一級快取就清空。
3.二級快取
首先開啟mybatis的二級快取
SQLSession去查詢使用者id為1的使用者資訊,查詢到使用者資訊會將查詢資料儲存到二級快取中
如果SQLSession去執行相同mapper下sql,執行commit提交,清空該mapper下的二級快取區域的資料
SQLSession去查詢使用者id為1的使用者資訊,去快取中查中是否存在資料,如果存在直接從快取中取出資料
二級快取與一級快取區別:二級快取的範圍更大,多個SQLSession可以共享一個UserMapper二級快取
UserMapper有一個二級快取區域(按照namespace分),其他的mapper也有自己的快取區域(按照namespace分)
每一個namespace的mapper有一個二級快取區域,如果倆個mapper的namespace如果相同,這倆個
mapper執行sql查詢到的資料就存在相同的二級快取區域中
3.1開啟二級快取
mybatis的二級快取是mapper範圍級別,除了在SqlMapConfig.xml設定二級快取的總開關,還要在具體的mapper.xml
中開啟二級快取
二級快取使用,需要在主檔案中進行配置:
①啟用二級快取
<!-- 啟用二級快取 -->
<setting name="cacheEnabled" value="true"/>
在UserMapper中開啟二級快取,UserMapper.xml下的sql執行完成會儲存到它的快取區域(HashMap)、
<mapper namespace="mybaties.mapper.User,apper">
<!--開啟本mapper的namespace下的二級快取-->
<cache/>
3.2呼叫pojo類實現序列化介面
public class User implements Serializables{
private int id;
private String username;
private String sex;
private Date birthday;
private String address;
}
為了將快取的資料取出執行序列化操作,因為二級快取的儲存介質多種多樣,不一定在記憶體
3.3測試方法
public testCacher2() throws Exception{
SqlSession sqlSesssion=sqlSessionFactory.openSession();
SqlSession sqlSesssion2=sqlSessionFactory.openSession();
SqlSession sqlSesssion3=sqlSessionFactory.openSession();
//建立代理物件
UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
//下邊查詢使用一個SqlSession
//第一次發起請求,查詢id為1的使用者
User uyser=userMapper.findUserById(1);
System.out.println(:user1);
//這裡執行關閉操作,將SQLSession中的資料寫到二級快取區域
SQLSession.close();
//使用SQLSession執行commit()操作
UserMapper userMapper3=sqlSession3.getMapper(UserMapper.class);
User user=userMapper3.findUserById(1);
user.setUsername(“測試使用者22”);
userMapper3.updateUser(user1);
//執行commint操作去清除快取
SQLSession3.commit();
SQLSession3.close();
UserMapper userMapper2=sqlSession2.getMapper(UserMapper.class);
//第二次發起請求,查詢id為1的使用者
User user2=userMapper2.findUserById(1);
Stystem.out.println(user2);
sqlSession2.close();
}
3.4useCache配置
①.設定useCache=false可以禁用當前select語句的二級快取,即每次查詢都會發出sql去查詢,預設情況是true,即該sql使用二級快取。
<select id="findOrderListResultMap" resultMap="ordersUserMap" useCache="false">
總結:針對每次查詢都需要最新的資料sql,要設定成useCache=false,禁用二級快取。
②.清空快取
<insert id="insertUser" parameterType="cn.itcast.mybatis.po.User" flushCache="true">
總結:一般下執行完commit操作都需要重新整理快取,flushCache=true表示重新整理快取,這樣可以避免資料庫髒讀。
注意:
(1)當為select語句時:
flushCache預設為false,表示任何時候語句被呼叫,都不會去清空本地快取和二級快取。
useCache預設為true,表示會將本條語句的結果進行二級快取。
(2)當為insert、update、delete語句時:
flushCache預設為true,表示任何時候語句被呼叫,都會導致本地快取和二級快取被清空。
useCache屬性在該情況下沒有。
當為select語句的時候,如果沒有去配置flushCache、useCache,那麼預設是啟用快取的,所以,如果有必要,那麼就需要人工修改配置
4.mybatis整合ehcache
4.1分散式快取
我們系統為了提高系統併發,效能。一般對系統進行分散式部署。(叢集部署方式)
不使用分佈緩衝池快取的資料在各自伺服器單獨儲存,不方便系統開發,所以要對分散式快取對快取資料進行集中管理
mybatis無法實現分散式快取。需要和其他分散式快取框架進行整合
4.2整合的方法
mybatis提供了一個cache介面,如果要實現自己的儲存邏輯,實現cache介面開發即可
mybatis和ehcache整合,mybatis和ehcache集合包中提供了一個cache介面的實現類
public interface Cache{
String getId();
void putObject(Object key ,Object value);
Object getObject(Object key);
}
mybatis預設實現的cache類是
public class PerpetualCache implements Cache{
private String id;
private Map<Object,Object> cache=new HashMap<Object,Object>();
public PerpetualCache(String id){
this.id=id;
}
public String getId(){
return id;
}
}
4.3配置資訊
配置mapper中的cache中的type為ehcache對cache介面的實現
<mapper namespace="mybatis.mapper.UserMapper">
<!-- 開啟mapper的namespace下的二級快取
type:指定Cache介面的實現類的型別,mybatis預設使用PerpetualCache
要和ehcache整合:需要配置type為ehcache實現cache介面型別
-->
<caahe type="org.mybatis.caches.ehcache.EhcacheCache"/>
3.4加入ehcache包
ehcache-core-2.6.5.jar
mybatis-ehcache-1.0.2jar
3.5加入ehcache的配置檔案
在classpath下配置
1 <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
2 xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
3 <diskStore path="F:\develop\ehcache" />
4 <defaultCache
5 maxElementsInMemory="1000"
6 maxElementsOnDisk="10000000"
7 eternal="false"
8 overflowToDisk="false"
9 timeToIdleSeconds="120"
10 timeToLiveSeconds="120"
11 diskExpiryThreadIntervalSeconds="120"
12 memoryStoreEvictionPolicy="LRU">
13 </defaultCache>
14 </ehcache>
屬性說明:
diskStore:指定資料在磁碟中的儲存位置。
defaultCache:當藉助CacheManager.add("demoCache")建立Cache時,EhCache便會採用<defalutCache/>指定的的管理策略
以下屬性是必須的:
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二級快取應用場景
應用場景:
對於訪問多的查詢請求且使用者對查詢結果實時性要求不高,此時可採用mybatis二級快取技術降低資料庫訪問量,提高訪
問速度,業務場景比如:耗時較高的統計分析sql、電話賬單查詢sql等。實現方法如下:通過設定重新整理間隔時間,由mybatis每隔一段時
間自動清空快取,根據資料變化頻率設定快取重新整理間隔flushInterval,比如設定為30分鐘、60分鐘、24小時等,根據需求而定。
5.侷限性:
mybatis二級快取對細粒度的資料級別的快取實現不好,比如如下需求:對商品資訊進行快取,由於商品資訊查詢訪問量大,
但是要求使用者每次都能查詢最新的商品資訊,此時如果使用mybatis的二級快取就無法實現當一個商品變化時只重新整理該商品的緩
存資訊而不重新整理其它商品的資訊,因為mybaits的二級快取區域以mapper為單位劃分,當一個商品資訊變化會將所有商品資訊
的快取資料全部清空。解決此類問題需要在業務層根據需求對資料有針對性快取。