Mybatis的二级缓存是多个SqlSession共享的,作用于是mapper配置文件中同一个namespace,不同的SqlSession两次执行相同namespace下的sql语句且参数如果也一样则最终执行的sql语句是相同的。每次查询都会先看看缓存中是否有对应查询结果,如果有就从缓存拿,如果没有就执行sql语句从数据库中读取,从而提高查询效率。Mybatis默认开启的是一级缓存,所以二级缓存需要自己手动开启。
开启二级缓存
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
添加redis依赖
org.springframework.boot
spring-boot-starter-data-redis
org.apache.commons
commons-pool2
//redisTemplate
@Bean
public RedisTemplate
该接⼝为标记接⼝,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;
}
}
//自定义缓存
@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;
}
}
对于有不需要用到二级缓存的语句可以在标签内写userCache=“false”,默认为true开启缓存。
(select 默认useCache为true:使用缓存,flushCache为false:不清空缓存)
(insert、update、delete 默认flushCache为true:清空缓存)