美文网首页
Springboot mybatis redis二级缓存

Springboot mybatis redis二级缓存

作者: 杨健kimyeung | 来源:发表于2020-08-22 10:43 被阅读0次

一、Redis作为二级缓存

Mybatis的二级缓存可以自动地对数据库的查询做缓存,并且可以在更新数据时同时自动地更新缓存。

实现Mybatis的二级缓存很简单,只需要新建一个类实现org.apache.ibatis.cache.Cache接口即可。

该接口共有以下五个方法:

方法
String getId() mybatis缓存操作对象的标识符。一个mapper对应一个mybatis的缓存操作对象
void putObject(Object key, Object value) 将查询结果存入缓存
Object getObject(Object key) 从缓存中获取被缓存的查询结果
Object removeObject(Object key) 从缓存中删除对应的key、value。只有在回滚时触发。一般我们也可以不用实现
void clear() 发生更新时,清除缓存。
int getSize() 可选实现。返回缓存的数量。
ReadWriteLock getReadWriteLock() 可选实现。用于实现原子性的缓存操作

二、实现Cache接口:

public class RedisCache implements Cache {
    private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
    private final String id;
    private RedisTemplate redisTemplate;
    //redis过期时间
    private static final long EXPIRE_TIME_IN_MINUTES = 30;

    public RedisCache(String id){
        if (id == null){
            throw  new IllegalArgumentException("Cache instance required an ID");
        }
        this.id = id;
    }

    @Override
    public String getId() {
        return id;
    }
    @Override
    public void putObject(Object key, Object value) {
        RedisTemplate redisTemplate = getRedisTemplate();
        ValueOperations opsForValue = redisTemplate.opsForValue();
        opsForValue.set(key.toString(),value,EXPIRE_TIME_IN_MINUTES, TimeUnit.MINUTES);
    }

    @Override
    public Object getObject(Object key) {
        RedisTemplate redisTemplate = getRedisTemplate();
        ValueOperations opsForValue = redisTemplate.opsForValue();
        return opsForValue.get(key.toString());
    }

    @Override
    public Object removeObject(Object key) {
        RedisTemplate redisTemplate = getRedisTemplate();
        redisTemplate.delete(key);
        return null;
    }

    @Override
    public void clear() {
        RedisTemplate redisTemplate = getRedisTemplate();
        redisTemplate.execute((RedisCallback) connection -> {
            connection.flushDb();
            return null;
        });
    }

    @Override
    public int getSize() {
        Long size = (Long) redisTemplate.execute((RedisCallback) connection -> connection.dbSize());
        return size.intValue();
    }

    @Override
    public ReadWriteLock getReadWriteLock() {
        return readWriteLock;
    }

    private RedisTemplate getRedisTemplate() {
        if(redisTemplate == null){
            redisTemplate = ApplicationContextHolder.getBean("redisTemplate");
        }
        return redisTemplate;
    }
}

ApplicationContextHolder

@Component
public class ApplicationContextHolder implements ApplicationContextAware, DisposableBean {
    private static ApplicationContext applicationContext;
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        ApplicationContextHolder.applicationContext = applicationContext;
    }

    public static ApplicationContext getApplicationContext(){
        checkApplicationContext();
        return applicationContext;
    }

    public static <T> T getBean(String name){
        checkApplicationContext();
        return (T) applicationContext.getBean(name);
    }

    public static <T> T getBean(Class<T> clazz){
        checkApplicationContext();
        return (T) applicationContext.getBeansOfType(clazz);
    }

    public static void cleanApplicationContext(){
        applicationContext = null;
    }

    private static void checkApplicationContext(){
        if(applicationContext ==null){
            if (applicationContext == null){
                throw new IllegalStateException("applicationContext未注入,请在applicationContext.xml中定义SpringContext");
            }
        }
    }

    @Override
    public void destroy() throws Exception {

    }
}

关键点

  1. 自己实现的二级缓存,必须要有一个带id的构造函数,否则会报错。
  2. 我们使用Spring封装的redisTemplate来操作Redis
  3. 我们采用的redis序列化方式是默认的jdk序列化。所以数据库的查询对象需要实现Serializable接口。

三、开启二级缓存

接下来,我们需要在Mapper.xml中开启二级缓存:

<?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="">
    <!-- 开启基于redis的二级缓存 -->
    <cache type="com.xxx.MybatisRedisCache"/>
</mapper>

标签属性说明

  • eviction:定义缓存移除机制(算法),默认为LRU(最近最少使用),它会清除最少使用的数据,还有一种FIFO(先进先出),它会清除最先进来的数据。

  • flushInterval:定义缓存刷新周期,单位为毫秒。

  • size:标识缓存cache中容纳的最大元素,默认为1024。

  • readOnly:默认为false,可配置为true缓存只读。

对于有不需要用到二级缓存的语句可以在标签内写userCache="false",默认为true开启缓存。

<select id="get" ... useCache="false">

</select>

<insert | update | delete id="" ... flushCache="false">

</select>

要点

  • select 默认useCache为true:使用缓存,flushCache为false:不清空缓存
  • insert、update、delete 默认flushCache为true:清空缓存

相关文章

网友评论

      本文标题:Springboot mybatis redis二级缓存

      本文链接:https://www.haomeiwen.com/subject/gvtvjktx.html