Springboot+Mybatis+redis实现二级缓存

Mybatis的二级缓存是多个SqlSession共享的,作用于是mapper配置文件中同一个namespace,不同的SqlSession两次执行相同namespace下的sql语句且参数如果也一样则最终执行的sql语句是相同的。每次查询都会先看看缓存中是否有对应查询结果,如果有就从缓存拿,如果没有就执行sql语句从数据库中读取,从而提高查询效率。Mybatis默认开启的是一级缓存,所以二级缓存需要自己手动开启。

application.yml

开启二级缓存

mybatis:
  mapper-locations: classpath:com/baizhi/mapper/*.xml
  executor-type: batch
  type-aliases-package: com.baizhi.entities
  #开启二级缓存
  configuration:
    cache-enabled: true

配置redis

  #redis配置
  redis:
    host: 192.168.192.19
    port: 6379
    timeout: 5s
    lettuce:
      shutdown-timeout: 100ms
      pool:
        max-active: 8
        max-idle: 8
        max-wait: 10ms
        min-idle: 1

pom.xml

添加redis依赖


    
      org.springframework.boot
      spring-boot-starter-data-redis

 
      org.apache.commons
      commons-pool2
 

添加redisTemplate配置Bean

 //redisTemplate
    @Bean
    public RedisTemplate redisTemplate(LettuceConnectionFactory connectionFactory) throws UnknownHostException {
        RedisTemplate redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(connectionFactory);
        //设置key,value序列化
        redisTemplate.setKeySerializer(new JdkSerializationRedisSerializer());
        redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        return redisTemplate;
    }

实现ApplicationContextAware

该接⼝为标记接⼝,Spring⼯⼚在初始化的时,会⾃动注⼊applicationContext

@Component
public class SpringContextHolder  implements ApplicationContextAware {
    private static ApplicationContext applicationContext;

    @Override
    //实现ApplicationContextAware接口的context注入函数, 将其存入静态变量
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    //从静态变量ApplicationContext中取得Bean
    public static Object getBeanByName(String name){
        Object bean = applicationContext.getBean(name);
        return bean;
    }
}

自定义MyBatisCache实现Cache

//自定义缓存
@Slf4j
public class MyCache implements Cache {
    private final String id;

    //redis缓存失效时间
    private Long timeout = 300L;

    private RedisTemplate redisTemplate;

    public MyCache(String id){
        this.id = id;
    }

    // 读写锁
    private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock(true);

    @Override
    public String getId() {
        return id;
    }

    @Override
    //加入缓存,第一次查询
    public void putObject(Object key, Object value) {
        log.info("====加入缓存key:"+key+",value:"+ value +",id:"+id+",第一次查询数据库=======");
        redisTemplate = getRedisTemplate();
        ValueOperations opsForValue = redisTemplate.opsForValue();
        opsForValue.set(key,value,timeout, TimeUnit.MINUTES);
    }

    @Override
    //查询首先查看缓存
    public Object getObject(Object key) {
        log.info("====查询前首先查看缓存key:"+key+"=id:"+id+"======");
        redisTemplate = getRedisTemplate();
        ValueOperations opsForValue = redisTemplate.opsForValue();
        return opsForValue.get(key);
    }

    @Override
    public Object removeObject(Object key) {
        log.info("====数据库写操作,删除当前缓存key:"+key+"=======");
        redisTemplate = getRedisTemplate();
        ValueOperations opsForValue = redisTemplate.opsForValue();
        Object value = opsForValue.get(key);
        redisTemplate.delete(key);
        return value;
    }

    @Override
    //一旦修改了数据库删除缓存
    public void clear() {
        log.info("====清除所有缓存id:"+id+"=======");
        redisTemplate = getRedisTemplate();
        redisTemplate.execute((RedisConnection connection) ->{
            connection.flushAll();
            return null;
        });
    }

    @Override
    public int getSize() {
        return 0;
    }

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

    public void setTimeout(Long timeout){
        this.timeout = timeout;
    }

    private RedisTemplate getRedisTemplate() {
        if (redisTemplate == null) {
            redisTemplate = (RedisTemplate) SpringContextHolder.getBeanByName("redisTemplate");
        }
        return redisTemplate;
    }
}

Mapper.xml




    
    
        
    

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

 
    

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

你可能感兴趣的:(Springboot+Mybatis+redis实现二级缓存)