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依赖

<!--redis-->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
 <dependency>
      <groupId>org.apache.commons</groupId>
      <artifactId>commons-pool2</artifactId>
 </dependency>

添加redisTemplate配置Bean

 //redisTemplate
    @Bean
    public RedisTemplate<Object,Object> redisTemplate(LettuceConnectionFactory connectionFactory) throws UnknownHostException {
        RedisTemplate<Object,Object> 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

<?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="com.baizhi.dao.IUserDAO">
    <!--开启二级缓存-->
    <cache type="com.baizhi.cache.MyCache">
        <property name="timeout" value="1000"/>
    </cache>

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

 <!--模糊分页查询-->
    <select id="queryUserByPage" resultType="User" useCache="false" flushCache="false">
        select <include refid="selectAll"/> from t_user
        <where>
            <if test="column != null and column != '' and value != ''">
                ${column} like "%"#{value}"%"
            </if>
        </where>
        limit #{pageNow},#{pageSize}
    </select>

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

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值