Mybatis使用Redis作爲二級緩存
-
SSM整合在這裏不在闡述了,可以看我另一篇帖子、裏邊也集成了redis、quartz等
-
git地址:ssm+redis+quartz
博客地址:ssm blog -
框架整合之後,我們直接上代碼使用redis作爲mybatis的二級緩存
-
首先我們在pom.xml添加依賴commons-codec,我們使用裏邊的一個方法,按照一定的規則生成key
DigestUtils.md5Hex(key)
<common-codec.version>1.12</common-codec.version>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>${common-codec.version}</version>
</dependency>
- 我們新建一個類實現Cache接口,重寫裏邊的方法
package com.bootdu.redis;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.ibatis.cache.Cache;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* 使用Redis緩存作爲Mybatis二級緩存
*/
public class RedisCache implements Cache {
//slf4j的日誌記錄器
private static final Logger logger = LoggerFactory.getLogger(RedisCache.class);
//緩存對象唯一標識
private final String id; //orm的框架都是按對象的方式緩存,而每個對象都需要一個唯一標識.
//用於事務性緩存操作的讀寫鎖
private static ReadWriteLock readWriteLock = new ReentrantReadWriteLock(); //處理事務性緩存中做的
//操作數據緩存的--跟着線程走的
public static RedisTemplate redisTemplate; //Redis的模板負責將緩存對象寫到redis服務器裏面去
//緩存對象的是失效時間,60分鐘
private static final long EXPRIRE_TIME_IN_MINUT = 60;
//生成key
private final String COMMON_CACHE_KEY = "com:bootdu:";
/**
* 所有key
*/
private String getKeys() {
return COMMON_CACHE_KEY + this.id + ":*";
}
/**
* 按照一定規則標識key
*/
private Object getKey(Object key) {
return COMMON_CACHE_KEY + this.id + ":" + DigestUtils.md5Hex(String.valueOf(key));
}
public static void setRedisTemplate(RedisTemplate redisTemplate) {
RedisCache.redisTemplate = redisTemplate;
}
//構造方法---把對象唯一標識傳進來
public RedisCache(String id) {
if (id == null) {
throw new IllegalArgumentException("緩存對象id是不能爲空的");
}
this.id = id;
}
@Override
public String getId() {
return this.id;
}
//給模板對象RedisTemplate賦值,並傳出去
public RedisTemplate getRedisTemplate() {
return redisTemplate;
}
/*
*保存緩存對象的方法
*/
@Override
public void putObject(Object key, Object value) {
try {
RedisTemplate redisTemplate = getRedisTemplate();
//使用redisTemplate得到值操作對象
ValueOperations operation = redisTemplate.opsForValue();
//使用值操作對象operation設置緩存對象
operation.set(getKey(key), value, EXPRIRE_TIME_IN_MINUT, TimeUnit.MINUTES); //TimeUnit.MINUTES系統當前時間的分鐘數
logger.debug("緩存對象保存成功,key{}", getKey(key));
} catch (Throwable t) {
logger.error("緩存對象保存失敗" + t, getKey(key));
}
}
/*
*獲取緩存對象的方法
*/
@Override
public Object getObject(Object key) {
try {
RedisTemplate redisTemplate = getRedisTemplate();
ValueOperations operations = redisTemplate.opsForValue();
Object result = operations.get(getKey(key));
logger.debug("獲取緩存對象", getKey(key));
return result;
} catch (Throwable t) {
logger.error("緩存對象獲取失敗" + t, getKey(key));
return null;
}
}
/*
刪除緩存對象
*/
@Override
public Object removeObject(Object key) {
try {
RedisTemplate redisTemplate = getRedisTemplate();
redisTemplate.delete(getKey(key));
logger.debug("刪除緩存對象成功!", getKey(key));
} catch (Throwable t) {
logger.error("刪除緩存對象失敗!" + t, getKey(key));
}
return null;
}
/*
清空緩存對象
當緩存的對象更新了的化,就執行此方法
*/
@Override
public void clear() {
RedisTemplate redisTemplate = getRedisTemplate();
//回調函數
Set<String> keys = redisTemplate.keys(getKeys());
redisTemplate.delete(keys);
logger.debug("清空緩存對象成功!", keys);
}
//可選實現的方法
@Override
public int getSize() {
return 0;
}
@Override
public ReadWriteLock getReadWriteLock() {
return readWriteLock;
}
}
6.我們要使用一個RedisTemplate,然後將它注入到我們上邊的類,在redis.xml配置文件種配置
<bean id="stringRedisSerializer"
class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
<bean id="redisTemplate_mybatis" class="org.springframework.data.redis.core.RedisTemplate">
<property name="connectionFactory" ref="redisConnectionFactory"></property>
<property name="keySerializer" ref="stringRedisSerializer"></property>
<property name="valueSerializer">
<bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/>
</property>
</bean>
7.我們構造一個類去注入redisTemplate
package com.bootdu.redis;
import org.springframework.data.redis.core.RedisTemplate;
/**
* 構造一個RedisTemplate注入
*/
public class MybatisRedisCacheTransfer {
public void setRedisTemplate(RedisTemplate redisTemplate) {
RedisCache.setRedisTemplate(redisTemplate);
}
}
----------------------------------------------------------------------
redis.xml 將redisTemplate_mybatis 注入到這裏
<!--注入-->
<bean class="com.bootdu.redis.MybatisRedisCacheTransfer">
<property name="redisTemplate" ref="redisTemplate_mybatis"></property>
</bean>
- 我們在需要使用緩存的接口對應的mapper.xml種配置這個緩存實現類
<!--使用Redis緩存作爲MyBatis二級緩存-->
<cache type="com.bootdu.redis.RedisCache"/>
- 測試:頁面可以請求到
我們看下控制檯:第一請求進來的時候,我們看到,在緩存中沒有找到執行了查詢,然後並緩存到redis裏邊
我們刷新請求下,再看控制檯:
這次沒有sql執行 而是直接去了緩存種查詢了,看到這樣,就成功了
至此我們整合redis作爲mybatis二級緩存已經完成了,思路:
1:創建一個類實現Mybatis Cache接口,重寫裏邊的方法
2:構造一個RedisTemplate 注入RedisTemplate
3:在mapper接口對應的xml文件種配置標籤,type寫我們Cache接口的實現類
Ps:注意,我們實體Po一定要實現序列化接口,不然在反序列化的時候要抱異常