需求
因有些数据查询量很大,很费数据库资源,且每次查询都是不怎么变更的数据,所以需要通过缓存进行减轻数据库压力,继而选择通过myabtis
的二级缓存来实现。
使用步棸
第一步:yml配置需开启mybatis-plus
的二级缓存。
# MyBatis Plus的配置项
mybatis-plus:
configuration:
# 是否开启缓存
cache-enabled: true
第二步:如果使用mybatis-plus
的二级缓存,则须在数据层(dao层)通过@CacheNamespace
注解来指定redis
的缓存实现工具类。
点击查看MybatisRedisCache 缓存工具类代码
import cn.hutool.extra.spring.SpringUtil;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.cache.Cache;
import org.springframework.data.redis.core.RedisTemplate;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* MybatisRedisCache 缓存工具类
* Title: MybatisRedisCache
* Description: redis缓存工具类
*
* @author lcl
*/
@Slf4j
public class MybatisRedisCache implements Cache
{
private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
// cache instance id
private final String id;
// 缓存模板
private RedisTemplate redisTemplate;
// redis过期时间
private static final long EXPIRE_TIME_IN_MINUTES = 30;
public MybatisRedisCache(String id)
{
if (id == null)
{
throw new IllegalArgumentException("Cache instances require an ID");
}
this.id = id;
}
@Override
public String getId()
{
return id;
}
/**
* Put query result to redis
*
* @param key
* @param value
*/
@Override
public void putObject(Object key, Object value)
{
try
{
redisTemplate = getRedisTemplate();
if (value != null)
{
redisTemplate.opsForValue().set(key.toString(), value, EXPIRE_TIME_IN_MINUTES, TimeUnit.MINUTES);
}
log.debug("Put query result to redis");
}
catch (Throwable t)
{
log.error("Redis put failed", t);
}
}
/**
* Get cached query result from redis
*
* @param key
* @return
*/
@Override
public Object getObject(Object key)
{
try
{
redisTemplate = getRedisTemplate();
log.debug("Get cached query result from redis");
return redisTemplate.opsForValue().get(key.toString());
}
catch (Throwable t)
{
log.error("Redis get failed, fail over to db", t);
return null;
}
}
/**
* Remove cached query result from redis
*
* @param key
* @return
*/
@Override
@SuppressWarnings("unchecked")
public Object removeObject(Object key)
{
try {
redisTemplate = getRedisTemplate();
redisTemplate.delete(key.toString());
log.debug("Remove cached query result from redis");
} catch (Throwable t) {
log.error("Redis remove failed", t);
}
return null;
}
/**
* Clears this cache instance
*/
@Override
public void clear()
{
redisTemplate = getRedisTemplate();
Set<String> keys = redisTemplate.keys("*:" + this.id + "*");
if (!CollectionUtils.isEmpty(keys))
{
redisTemplate.delete(keys);
}
log.debug("Clear all the cached query result from redis");
}
/**
* This method is not used
*
* @return
*/
@Override
public int getSize()
{
return 0;
}
@Override
public ReadWriteLock getReadWriteLock()
{
return readWriteLock;
}
private RedisTemplate getRedisTemplate()
{
if (redisTemplate == null) {
redisTemplate = SpringUtil.getBean("redisTemplate");
}
return redisTemplate;
}
}
第三步:如果想即使用mybatis-plus
又想使用mybatis
的xml手写sql高级查询,则需在xml文件中增加<cache-ref>
标签,并配置
命名空间。
<!--开启缓存-->
<cache-ref namespace="你的xml位置"/>
第四步:返回的数据对象需实现Serializable
序列化,否则会报错;因为开启二级缓存,一级缓存会写到磁盘中,二级缓存会写到内存中;