【SpringBoot+MyBatis】二级缓存以及使用Redis缓存数据

在MyBatis中,存在一级缓存以及二级缓存。一级缓存是默认自动开启,而二级缓存需要我们手动去开启。但看到这篇文章的人,大部分都是在做项目才发现的问题:每次访问数据都要查询一遍又一遍的数据库,这是在控制台上可以发现的。导致数据库压力很大(虽然一个人是看不出来的),但要是众多人使用的就会导致数据库压力大,这点可想而知。

这时候就需要启动MyBatis自带的二级缓存了。

使用二级缓存需要具备以下几个条件:

  • 1、在核心配置文件添加cache-enabled: true(全局性地开启或关闭所以映射器配置文件已配置的任何缓存)

但这是默认开启的,所以可以不用添加

  • 2、在需要的mapper映射文件中的里添加

  • 3、使用二级缓存的实体类对象必须是可序化的,也就是必须实现java.io.Serializable接口

  • 4、纯MyBatis中需要将SqlSession对象关闭或提交之后,一级缓存才会被写入二级缓存中,此时二级缓存才可用

总而言之就是两步:1、所有的Mapper.xml文件配置;2、所有实体类继承序列化接口

 

这样子二级缓存就开启了。每次查询同一条Sql就只会返回一次查询记录。

那么问题又来了,为什么我们已经做到这个地步了还需要使用Redis这个NoSQL呢?虽然MyBatis的二级缓存已经挺好用了,但在分布式集群环境下,应用部署在不同的服务器当中,根据负载均衡的原理,查询的操作可以会访问不同的服务器,如果其中的一个服务器断电什么的,那么缓存就不存在了,就又需要再次查询数据库。所以说需要使用分布式缓存来解决这个问题。

第一步:导入坐标


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

第二步:在yml配置中使用Redis相关配置

spring:
  #Redis相关配置
  redis:
    host: localhost
    #password:
    port: 6379
    database: 0 #操作的是0号数据库
    #Redis连接池配置
    pool:
      max-active: 8 #最大连接数
      max-wait: -1 #连接池最大阻塞等待时间 -1表示无限
      max-idle: 4 #连接池中的最大空闲连接
      min-idle: 0 #连接池中的最小空闲连接

第三步:MyBatis的缓存机制是通过其内部有个PerpetualCache类去实现Cache从而实现缓存的。那么我们同样可以写一个与其相同的类去存储。

import org.apache.ibatis.cache.Cache;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;

public class RedisCache implements Cache {
    //id指定当前放入缓存的mapper的namespace
    private final String id;
    private final RedisTemplate redisTemplate;

    public RedisCache(String id) {
        //获取Redis实例
        redisTemplate = ApplicationContextUtil.getBean("redisTemplate",RedisTemplate.class);
        //指定key的序列化方式
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        this.id = id;
    }

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

    @Override
    public void putObject(Object key, Object value) {
        redisTemplate.opsForHash().put(id,key.toString(),value);
    }

    @Override
    public Object getObject(Object key) {
        return redisTemplate.opsForHash().get(id,key.toString());
    }

    @Override
    public Object removeObject(Object key) {
        return redisTemplate.opsForHash().delete(id, key);
    }

    @Override
    public void clear() {
        redisTemplate.delete(id);
    }

    @Override
    public int getSize() {
        return redisTemplate.opsForHash().size(id).intValue();
    }
}

在自己完成的这个缓存机制类的有参构造通过ApplicationContextUtil去实例化Redis,需要注意的是,这里不能通过Autowire的方式引用redisTemplate,因为RedisCache并不是Spring容器里的bean。所以我们需要手动地去调用容器的getBean方法来拿到这个bean.所以说需要去写一个工具类去实现ApplicationContextAware,从而去获取上下文对象ApplicationContext,然后才能通过getBean去实例化Redis。

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ApplicationContextUtil implements ApplicationContextAware {
    //获取IoC容器
    private static ApplicationContext applicationContext;

    //实现了ApplicationContextAware接口后,重写setApplicationContext方法进行设置 
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    //通过在工厂中获取对象的方法
    public static  T getBean(String beanName,Class requiredType){
        return applicationContext.getBean(beanName,requiredType);
    }
}

第四步:将我们原先在MyBatis的二级缓存修改成

测试后就会发现控制台输出的和一开始的二级缓存一样,并且在Redis数据库中也存放了数据

【SpringBoot+MyBatis】二级缓存以及使用Redis缓存数据_第1张图片

 

你可能感兴趣的:(框架及实战,redis,数据库,缓存,SpringBoot,mybatis)