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
【Springboot+Mybatis+redis实现二级缓存】该接?为标记接?,Spring??在初始化的时,会?动注?applicationContext
@Component public class SpringContextHolderimplements 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 = https://www.it610.com/article/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 = https://www.it610.com/article/redisTemplate.opsForValue(); return opsForValue.get(key); }@Override public Object removeObject(Object key) { log.info("====数据库写操作,删除当前缓存key:"+key+"======="); redisTemplate = getRedisTemplate(); ValueOperations opsForValue = https://www.it610.com/article/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 from t_user ${column} like "%"#{value}"%" limit #{pageNow},#{pageSize}

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

    推荐阅读