利用MyBatis自身本地缓存结合Redis实现分布式缓存 (二)

请先看利用MyBatis自身本地缓存结合Redis实现分布式缓存 (一)

一、关于多表关系直接的缓存处理

  • 此时我们只测试了缓存对一个表的CRUD操作, 也完全可以实现分布式缓存的处理; 如果此时我们再创建一个emp表, 对emp表进行CRUD操作也是可行的; 但是User表和Emp表, 当清空User表的缓存对Emp表缓存没有任何影响;

  • 有人会说, 都是不同的表肯定没关系了, 其实说的也对, 假如说项目中表查询之间灭有任何关联查询, 使用上一篇文章就完全可以解决, 也不会出现任何问题;

  • 但是如果这两个表之间存在关联关系了呢? 此时问题就出现了, 比如我们再mybatis中所说的那样, 出现额外SQL的情况, 就涉及到多表的操作, 此时就会出现问题;

在这里插入图片描述
问题:

  • 比如User中包含了Emp属性, 当以后我们更像了Emp信息, 就会清空Emp中的缓存信息; 但是User的缓存还没有清空, 当下次再查询User的信息, 仍然查询到的是Emp更像前的信息;

使用<cache-ref namespace="com.zy.dao.UserDao"/>, 将多个有关联关系的表的缓存放到了一起;

二、缓存优化策略

  • 对放入redis中key进行优化; key的长度不要太长; MD5散列算法

在这里插入图片描述

/**
 * Description: 自定义Redis缓存实现
 *
 * @author zygui
 * @date Created on 2020/7/27 16:55
 */
public class RedisCache implements Cache {
    
    

    private final String id;

    // 必须存在构造方法
    public RedisCache(String id) {
    
    
        // id 就是当前放入缓存的mapper的namespace ---> com.zy.dao.UserDao
        System.out.println("id =============> " + id);
        this.id = id;
    }

    // 返回cache的唯一标识
    @Override
    public String getId() {
    
    
        return this.id;
    }

    // 往缓存中放值 --> 使用 RedisTemplate往缓存中放值
    // key ---> -983043073:3242099914:com.zy.dao.UserDao.findAll:0:2147483647:SELECT id, name, age, bir FROM t_user:SqlSessionFactoryBean
    @Override
    public void putObject(Object key, Object value) {
    
    
        // 使用hash类型作为缓存存储模型 <key, <hashkey, value>>  ==> <namespace <当前方法的key, 返回值>>
        getRedisTemplate().opsForHash().put(id, getKeyToMD5(key.toString()), value);

    }

    // 往缓存中取值, 这个key
    // key ---> -983043073:3242099914:com.zy.dao.UserDao.findAll:0:2147483647:SELECT id, name, age, bir FROM t_user:SqlSessionFactoryBean
    @Override
    public Object getObject(Object key) {
    
    
        System.out.println("key = " + key);
        // 根据key从redis的hash类型中key获取数据
        return getRedisTemplate().opsForHash().get(id, getKeyToMD5(key.toString()));
    }

    // 为mybatis的保留方法, 默认没有实现
    @Override
    public Object removeObject(Object o) {
    
    
        System.out.println("根据指定key删除缓存");
        return null;
    }

    // 当执行增删改会调用这个方法
    @Override
    public void clear() {
    
    
        System.out.println("清空缓存");
        getRedisTemplate().delete(id); // 清空缓存
    }

    // 用来计算缓存数量
    @Override
    public int getSize() {
    
    
        // 获取hash中key value的数量
        return getRedisTemplate().opsForHash().size(id).intValue();
    }

    //封装redisTemplate
    private RedisTemplate getRedisTemplate(){
    
    
        //通过application工具类获取redisTemplate
        RedisTemplate redisTemplate = (RedisTemplate) ApplicationContextUtils.getBean("redisTemplate");
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        return redisTemplate;
    }

    // 封装一个对key进行md5的处理方法
    private String getKeyToMD5(String key) {
    
    
        return DigestUtils.md5DigestAsHex(key.getBytes());
    }
}

在这里插入图片描述
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/m0_37989980/article/details/107617915