1. Mybatis提供了查詢緩存的功能,用於減輕數據庫查詢壓力,分別提供了一級緩存和二級緩存兩種緩存級別。java
2. 查詢緩存,就是將SQL查詢語句查詢的結果緩存中內存中(經過HashMap保存),若是屢次執行同一個查詢語句,就不須要每次都與數據庫進行一次會話(建立SqlSeesion對象發送SQL語句),而是直接從內存中取出查詢的結果,這樣就能夠提升性能,減小數據庫壓力。mysql
3. 一級緩存是SqlSession級別的緩存。在操做數據庫時須要構造 sqlSession對象,在對象中有一個數據結構(HashMap)用於存儲緩存數據。不一樣的sqlSession之間的緩存數據區域(HashMap)是互相不影響的。spring
4. 二級緩存是mapper級別的緩存,多個SqlSession去操做同一個Mapper的sql語句,多個SqlSession能夠共用二級緩存,二級緩存是跨SqlSession的。sql
1. 工做原理:以查詢用戶爲例,數據庫
2. Mybatis默認開啓一級緩存,因此不須要進行配置操做。apache
3. 應用:緩存
在正式開發中,是將mybatis和spring進行整合開發,事務控制在service中。 一個service方法中包括 不少mapper方法調用。 service(){ //開始執行時,開啓事務,建立SqlSession對象 //第一次調用mapper的方法findUserById(1) //第二次調用mapper的方法findUserById(1),從一級緩存中取數據 //方法結束,sqlSession關閉 } 若是是執行兩次service調用查詢相同 的用戶信息,不走一級緩存,由於session方法結束,sqlSession就關閉,一級緩存就清空。
1. 工做原理:首先要開啓二級緩存session
2. 二級緩存與一級緩存區別:二級緩存的範圍更大,多個sqlSession能夠共享一個UserMapper的二級緩存區域;其次二級緩存的位置不必定是內存中,也有多是硬盤或者其餘緩存介質。UserMapper有一個二級緩存區域(按namespace分) ,其它mapper也有本身的二級緩存區域(按namespace分)。每個namespace的mapper都有一個二緩存區域,兩個mapper的namespace若是相同,這兩個mapper執行sql查詢到數據將存在相同 的二級緩存區域中。數據結構
3. 配置開啓二級緩存:首先在Mybatis的啓動配置文件SqlMapConfig.xml中加入<setting name="cacheEnabled" value="true"/> ,而後在要開啓二級緩存的Mapper映射文件中添加<cache></cache> 標籤mybatis
<!--啓動配置文件--> <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <settings> <setting name="lazyLoadingEnabled" value="true"/> <setting name="aggressiveLazyLoading" value="false"/> <!--開啓二級緩存--> <setting name="cacheEnabled" value="true"/> </settings> <environments default="environment"> <environment id="environment"> <transactionManager type="JDBC" /> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://localhost:3306/cloud_note?useUnicode=true&characterEncoding=utf8" /> <property name="username" value="root" /> <property name="password" value="123456" /> </dataSource> </environment> </environments> <!--指定映射文件位置--> <mappers> <mapper resource="mapper/Usermapper.xml"/> </mappers> </configuration> <!--Mapper文件配置--> <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="dao.UserDao"> <!--開啓二級緩存--> <cache></cache> <select id="findUserById" parameterType="string" resultType="entity.User"> select * from cn_user where cn_user_id=#{id} </select> </mapper>
4. 禁用某SQL查詢語句的二級緩存:在statement中設置useCache=false能夠禁用當前select語句的二級緩存,即每次查詢都會發出sql去查詢,默認值是true,即該sql使用二級緩存。<select id="find" resultMap="UserMap" useCache="false">;針對每次查詢都須要最新的數據sql,要設置成useCache=false,禁用二級緩存。
5. 刷新緩存:在mapper的同一個namespace中,若是有其它insert、update、delete操做數據後須要刷新緩存,若是不執行刷新緩存會出現髒讀。設置statement配置中的flushCache="true" 屬性,默認值爲true即刷新緩存,若是改爲false則不會刷新。使用緩存時若是手動修改數據庫表中的查詢數據會出現髒讀。<insert id="insertUser" parameterType="cn.itcast.mybatis.po.User" flushCache="true">,通常都應該設置爲true
1. Mybatis中的二級緩存不支持分佈式緩存,要實現分佈式緩存須要與第三方緩存工具進行整合使用,經常使用的好比Redis、ehcache等。
2. 整合原理:mybatis提供了一個Cache接口, 若是要實現本身的緩存邏輯,實現cache接口開發便可。
import java.util.concurrent.locks.ReadWriteLock; import org.apache.ibatis.cache.Cache; public class MyCache implements Cache{ @Override public String getId() { return null; } @Override public void putObject(Object key, Object value) { } @Override public Object getObject(Object key) { return null; } @Override public Object removeObject(Object key) { return null; } @Override public void clear() { } @Override public int getSize() { return 0; } @Override public ReadWriteLock getReadWriteLock() { return null; } }
Mybatis默認使用的Cache實現類(實現二級緩存):使用HashMap實現
package org.apache.ibatis.cache.impl; import java.util.HashMap; import java.util.Map; import java.util.concurrent.locks.ReadWriteLock; import org.apache.ibatis.cache.Cache; import org.apache.ibatis.cache.CacheException; 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; } public int getSize() { return cache.size(); } public void putObject(Object key, Object value) { cache.put(key, value); } public Object getObject(Object key) { return cache.get(key); } public Object removeObject(Object key) { return cache.remove(key); } public void clear() { cache.clear(); } public ReadWriteLock getReadWriteLock() { return null; } public boolean equals(Object o) { if (getId() == null) throw new CacheException("Cache instances require an ID."); if (this == o) return true; if (!(o instanceof Cache)) return false; Cache otherCache = (Cache) o; return getId().equals(otherCache.getId()); } public int hashCode() { if (getId() == null) throw new CacheException("Cache instances require an ID."); return getId().hashCode(); } }
除此以外提供了多種緩存策略的實現類:
3. 配置使用第三方緩存工具:以mybatis和ehcache整合包中提供了一個cache接口的實現類爲例,
4. 二級緩存應用場景:對於訪問多的查詢請求且用戶對查詢結果實時性要求不高,此時可採用mybatis二級緩存技術下降數據庫訪問量,提升訪問速度,業務場景好比:耗時較高的統計分析sql、電話帳單查詢sql等。由於若是要求查詢結果數據實時性高,那麼仍然會頻繁的與數據進行交互,二級緩存就是去了意義;經過設置刷新間隔時間,由mybatis每隔一段時間自動清空緩存,根據數據變化頻率設置緩存刷新間隔flushInterval,好比設置爲30分鐘、60分鐘、24小時等,根據需求而定,在Mapper映射文件中的<cache>標籤指定flushInterval屬性的值便可,如<cache flushInterval="6000"></cache>,單位爲毫秒