您的位置:首页 > 数据库 > Redis

SpringBoot配置Redis对Mybatis的二级缓存进行缓存

2019-01-22 14:20 459 查看

Mybatis缓存分一级,二级
一级:sqlSession缓存,和数据库的一个会话,会话完成就关闭了。
二级:mapper缓存,整个服务期间都存在,所以redis对二级进行缓存。

开始配置二级缓存

  1. 在Mybatis配置文件中开启二级缓存
  2. 在XxxMapper.xml中开启当前mapper的namespace的二级缓存,可以在此处使用开启mapper二级缓存,也可以使用@CacheNamespace注解在关联的XxxMapper接口文件上启动二级缓存,两者只能选其一
<?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.cy.dao.SysPermMapper">
<cache-ref namespace="com.cy.dao.SysPermMapper"/>
<select id="getUser" resultMap="...">
select * from user ...
</select>
……
</mapper>
@Mapper
@CacheNamespace(eviction = MybatisRedisCache.class,implementation = MybatisRedisCache.class)
public interface SysPermMapper extends BaseMapper<SysPerm> {

List<User> getUser();
}
  1. 新建MybatisRedisCache,实现Cache接口并重写全部的抽象方法
package com.cy.crm.util;

import org.apache.ibatis.cache.Cache;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.RedisServerCommands;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;

import java.util.Set;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
* @ClassName MybatisRedisCache
* @Description Redis对Mybatis的缓存
* @Author Jack.Hu
*/
public class MybatisRedisCache implements Cache {

private static Logger log = LoggerFactory.getLogger(MybatisRedisCache.class);
// 读写锁
private final ReadWriteLock lock = new ReentrantReadWriteLock(true);

// 这里使用redis缓存,使用springBoot自动注入
@Autowired
private RedisTemplate<String, Object> redisTemplate;

private String id;

public MybatisRedisCache(final String id){
if(null == id){
throw new IllegalStateException("Cache instances require an ID");
}
this.id = id;
}

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

@Override
public void putObject(Object key, Object value) {
if(redisTemplate == null){
redisTemplate = (RedisTemplate<String, Object>) SpringContextHolder.getApplicationContext().getBean("redisJsonTemplate");
}
if(value != null){
redisTemplate.opsForValue().set(key.toString(),value);
}
}

@Override
public ReadWriteLock getReadWriteLock() {
return this.lock;
}

@Override
public Object getObject(Object key) {
try{
if(null != key){
return redisTemplate.opsForValue().get(key.toString());
}
}catch(Exception e){
log.error("缓存错误");
}
return null;
}

@Override
public Object removeObject(Object key) {
if(null != key){
return redisTemplate.delete(key.toString());
}
return null;
}

@Override
public void clear() {
log.debug("情空缓存");
if(null == redisTemplate){
redisTemplate = (RedisTemplate<String, Object>) SpringContextHolder.getApplicationContext().getBean("redisJsonTemplate");
}
Set<String> keys = redisTemplate.keys("*:" + this.id + "*");
for (String key : keys) {
redisTemplate.delete(key);
}
}

/**
* 获取缓存中的缓存数量
* @return
*/
@Override
public int getSize() { // 获取缓存中的缓存数量
return  redisTemplate.execute((RedisCallback<Long>) RedisServerCommands::dbSize).intValue();
}

}

注意:由于RedisTemplate的注入可能在应用启动期间没有成功进行注入到缓存内中,需要在使用缓存时中进行手动注入,这是需要从应用的上下文获取RedisTemplate,需要定义一个获取应用上下文的类实现ApplicationContextAware接口,通过这个类来获取应用上下文,通过应用上下文来获取注册到应用上下文的bean!

package com.cy.crm.util;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

/**
* @ClassName SpringContextHolder
* @Description TODO
* @Author Jack Hu
*/
@Component
public class SpringContextHolder implements ApplicationContextAware {

private static ApplicationContext applicationContext;

@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}

public static ApplicationContext getApplicationContext(){
assertApplicationContext();
return applicationContext;
}

public static <T>T getBean(String beanName){
assertApplicationContext();
return (T)applicationContext.getBean(beanName);
}

public static <T>T getBean(Class<T> requiredType){
assertApplicationContext();
return applicationContext.getBean(requiredType);
}

private static void assertApplicationContext(){
if(null == SpringContextHolder.applicationContext){
throw new RuntimeException("applicationContext属性为null,请检查是否注入成功!");
}
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: