面试官:小伙子,你给我说一下mybatis怎么实现Redis分布式缓存吧

1. Mybatis的缓存机制

面试官:小伙子,你给我说一下mybatis怎么实现Redis分布式缓存吧_第1张图片

一级缓存(默认开启):

SqlSession级的缓存:在同一个SqlSession 查询同一个数据,不需要再通过数据库查询

二级缓存:

SqlSessionFactory级的缓存:在所有的SqlSession 查询同一个数据,不需要再通过数据库查询 在mybatis的mapper.xml文件中加入标签:

  ---- 默认本地缓存复制代码

二级缓存实现原理:

mybatis的二级缓存主要在Executor对象上进行操作,当mybatis发现在mybatis.xml配置文件中设置了cacheEnabled=true时,mybatis在创建sqlsession时创建Executor对象,同时会对Executor加上装饰者【CacheExecutor】。 CacheExecutor对于查询请求,会判断application级别的二级缓存是否有缓存结果,如果有查询结果则直接返回,如果没有

2. 利用mybatis自身本地缓存结合redis实现分布式缓存

面试官:小伙子,你给我说一下mybatis怎么实现Redis分布式缓存吧_第2张图片

mybatis中应用二级缓存默认PepreCache SqlSessionFactory级别的缓存 所有SqlSession会话共享 如何开启(二级缓存) ---- 本地缓存 默认是使用了org.apache.ibatis.cache.impl.PerpetualCache实现

案例:

-->            复制代码

public class PerpetualCache implements Cache {private final String id;// 【必须】当前放入缓存的Mapper的 namespace 名称空间private final Map cache = new HashMap<>();public PerpetualCache(String id) {this.id = id;}// 返回cache的唯一标识@Overridepublic StringgetId() {returnid;}@Overridepublic intgetSize() {returncache.size();}// 缓存放入值// redis --- RedisTemplate  StringRedisTemplate// @Overridepublic void putObject(Object key, Object value) {cache.put(key, value);}// 从缓存中获取值@Overridepublic Object getObject(Object key) {returncache.get(key);}...}复制代码

自定义RedisCache实现

通过mybatis默认的 cachery源码得知,可以使用自定义Cache类 实现Cache接口,并对李米娜的方法进行实现 public class RedisCache implements Cache{…} 使用RedisCache实现

复制代码

细节:

RedisTemplate对象是自动注入到IOC容器中,然后通过ApplicationContext对象回去容器对象。 在Spring Boot 内部 提供接口 ApplicationContextAware 获取IOC容器ApplicationContext对象。然后通过applicationContext对象获取Redis操作对象 RedisTemplate 对象。

//用来获取springboot创建好的工厂@Configurationpublic class ApplicationContextUtils implements ApplicationContextAware {    //保留下来工厂    private static ApplicationContext applicationContext;    //将创建好工厂以参数形式传递给这个类    @Override    public voidsetApplicationContext(ApplicationContext applicationContext) throws BeansException {        this.applicationContext = applicationContext;    }        //提供在工厂中获取对象的方法 //RedisTemplate  redisTemplate    public static Object getBean(String beanName){returnapplicationContext.getBean(beanName);    }}复制代码

2.2 实现Cache接口,实现Redis分布式缓存

import com.baizhi.util.ApplicationContextUtils;import org.apache.ibatis.cache.Cache;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.data.redis.serializer.StringRedisSerializer;import org.springframework.util.DigestUtils;import java.util.concurrent.TimeUnit;//自定义Redis缓存实现public class RedisCache implements Cache {    //当前放入缓存的mapper的namespace    private final String id;    //必须存在构造方法    public RedisCache(String id) {        System.out.println("id:=====================> "+ id);        this.id = id;    }    //返回cache唯一标识    @Override    public StringgetId() {returnthis.id;    }    //缓存放入值  redis RedisTemplate  StringRedisTemplate    @Override    public void putObject(Object key, Object value) {        System.out.println("key:"+ key.toString());        System.out.println("value:"+ value);//        //通过application工具类获取redisTemplate//        RedisTemplate redisTemplate = (RedisTemplate) ApplicationContextUtils.getBean("redisTemplate");//        redisTemplate.setKeySerializer(new StringRedisSerializer());//        redisTemplate.setHashKeySerializer(new StringRedisSerializer());        //使用redishash类型作为缓存存储模型  key  hashkey  value        getRedisTemplate().opsForHash().put(id.toString(),getKeyToMD5(key.toString()),value);if(id.equals("com.baizhi.dao.UserDAO")){            //缓存超时  client  用户  client  员工            getRedisTemplate().expire(id.toString(),1, TimeUnit.HOURS);        }if(id.equals("com.baizhi.dao.CityDAO")){            //缓存超时  client  用户  client  员工            getRedisTemplate().expire(id.toString(),30, TimeUnit.MINUTES);        }        //.....指定不同业务模块设置不同缓存超时时间    }    //获取中获取数据    @Override    public Object getObject(Object key) {        System.out.println("key:"+ key.toString());//        //通过application工具类获取redisTemplate//        RedisTemplate redisTemplate = (RedisTemplate) ApplicationContextUtils.getBean("redisTemplate");//        redisTemplate.setKeySerializer(new StringRedisSerializer());//        redisTemplate.setHashKeySerializer(new StringRedisSerializer());        //根据key 从redis的hash类型中获取数据returngetRedisTemplate().opsForHash().get(id.toString(), getKeyToMD5(key.toString()));    }    //注意:这个方法为mybatis保留方法 默认没有实现 后续版本可能会实现    @Override    public Object removeObject(Object key) {        System.out.println("根据指定key删除缓存");returnnull;    }    @Override    public voidclear() {        System.out.println("清空缓存~~~");        //清空namespace        getRedisTemplate().delete(id.toString());//清空缓存    }    //用来计算缓存数量    @Override    public intgetSize() {        //获取hash中key value数量returngetRedisTemplate().opsForHash().size(id.toString()).intValue();    }    //封装redisTemplate    private RedisTemplategetRedisTemplate(){        //通过application工具类获取redisTemplate        RedisTemplate redisTemplate = (RedisTemplate) ApplicationContextUtils.getBean("redisTemplate");returnredisTemplate;    }    //封装一个对key进行md5处理方法    private String getKeyToMD5(String key){returnDigestUtils.md5DigestAsHex(key.getBytes());    }}复制代码


高级Java工程师之路

   

你可能感兴趣的:(面试官:小伙子,你给我说一下mybatis怎么实现Redis分布式缓存吧)