【MyBatis框架】查詢緩存-二級緩存-整合ehcache

mybatis整合ehcache
ehcache是一個分佈式緩存框架。java

1.分佈緩存
咱們系統爲了提升系統併發,性能、通常對系統進行分佈式部署(集羣部署方式)
mysql

如圖sql



不使用分佈緩存,緩存的數據在各各服務單獨存儲,不方便系統開發。因此要使用分佈式緩存對緩存數據進行集中管理。
mybatis沒法實現分佈式緩存,須要和其它分佈式緩存框架進行整合。

2.整合方法(掌握)
mybatis提供了一個cache接口,若是要實現本身的緩存邏輯,實現cache接口開發便可。
mybatis和ehcache整合,mybatis和ehcache整合包中提供了一個cache接口的實現類。
mybatis默認實現cache類(接口)是:
此接口在MyBatis-3.2.7.jar下的org.apache.ibatis.cache包下的Cache.class數據庫

package org.apache.ibatis.cache;

import java.util.concurrent.locks.ReadWriteLock;

public interface Cache {
  
    //緩存在惟一標示
    String getId();
  
    //存入到緩存中
    void putObject(Object key, Object value);
 
    //根據key取出緩存
     Object getObject(Object key);

    //移除key 
     Object removeObject(Object key);

      void clear();

     int getSize();
  
    ReadWriteLock getReadWriteLock();
}

MyBatis默認實現支持的cache類是:apache

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.加入ehcache包
ehcache-core-2.6.5.jar和mybatis-ehcache-1.0.2.jar
一個是ehcache本身的,一個是和mybatis的整合包

4.整合ehcache
配置mapper中cache中的type爲ehcache對cache接口的實現類型。
咱們在mybatis-ehcache-1.0.2.jar下找到org.mybatis.caches.ehcache包下有EhcacheCache.class類,這個就是ehcache整合mybatis的Cache接口的實現
UserMapper.xml:緩存

<mapper namespace="cn.edu.hpu.mybatis.mapper.UserMapper">

    <!-- 開啓本Mapper的namespace下的二級緩存 
    type:執行cache接口實現類的類型,mybatis默認使用PerpatualCache,
    要和ehcache整合,須要配置type爲ehcache實現cache接口的類型-->
    <cache type="org.mybatis.caches.ehcache.EhcacheCache"/>
    ......
</mapper>

5.加入ehcache的配置文件

在classpath下配置ehcache.xmlmybatis

<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>

測試:併發

//測試二級緩存
    @Test
    public void testCache2() throws Exception{
        SqlSession sqlSession1 = sqlSessionFactory.openSession();
        SqlSession sqlSession2 = sqlSessionFactory.openSession();
        SqlSession sqlSession3 = sqlSessionFactory.openSession();
        
        UserMapper userMapper1 = sqlSession1.getMapper(UserMapper.class);//建立代理對象
        //下邊查詢使用一個SqlSession
        //第一次發起請求,查詢id爲1的用戶
        User user1 = userMapper1.findUserById(1);
        System.out.println(user1.getUsername());
        //不關閉SqlSession沒法寫進二級緩存區域中
        sqlSession1.close();
        
        UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class);//建立代理對象
        //第二次發起請求,查詢id爲1的用戶
        User user2 = userMapper2.findUserById(1);
        System.out.println(user2.getUsername());
        sqlSession2.close();
}

結果和輸出日誌:app

DEBUG [main] - Cache Hit Ratio [cn.edu.hpu.mybatis.mapper.UserMapper]: 0.0
DEBUG [main] - Opening JDBC Connection
DEBUG [main] - Created connection 4554017.
DEBUG [main] - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.Connection@457d21]
DEBUG [main] - ==>  Preparing: SELECT * FROM USER WHERE id=? 
DEBUG [main] - ==> Parameters: 1(Integer)
DEBUG [main] - <==      Total: 1
張明明
DEBUG [main] - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.Connection@457d21]
DEBUG [main] - Closing JDBC Connection [com.mysql.jdbc.Connection@457d21]
DEBUG [main] - Returned connection 4554017 to pool.
DEBUG [main] - Cache Hit Ratio [cn.edu.hpu.mybatis.mapper.UserMapper]: 0.5
張明明

整合ehcache成功!框架

6.二級應用場景對於訪問多的查詢請求且用戶對查詢結果實時性要求不高,此時可採用mybatis二級緩存技術下降數據庫訪問量,提升訪問速度,業務場景好比:耗時較高的統計分析sql、電話帳單查詢sql等。實現方法以下:經過設置刷新間隔時間,由mybatis每隔一段時間自動清空緩存,根據數據變化頻率設置緩存刷新間隔flushInterval,好比設置爲30分鐘、60分鐘、24小時等,根據需求而定。7.二級緩存侷限性mybatis二級緩存對細粒度的數據級別的緩存實現很差,好比以下需求: 對商品信息進行緩存,因爲商品信息查詢訪問量大,可是要求用戶每次都能查詢最新的商品信息,此時若是使用mybatis的二級緩存就沒法實現當一個商品變 化時只刷新該商品的緩存信息而不刷新其它商品的信息,由於mybaits的二級緩存區域以mapper爲單位劃分,當一個商品信息變化會將全部商品信息的 緩存數據所有清空。解決此類問題須要在業務層根據需求對數據有針對性緩存。

相關文章
相關標籤/搜索