Spring Cache常见问题解决

目录

[一 报错:Null key returned for cache operation](#一 报错:Null key returned for cache operation)

[二 报错:类型转换异常](#二 报错:类型转换异常)

[三 取出的数据为null](#三 取出的数据为null)


一 报错:Null key returned for cache operation

这里报错有两种情况:

第一,如果你在新增的方法上使用Cacheable注解,那么肯定是会报这个错误的。

因为Cacheable注解的原理是先根据key去Redis查看有没有这个缓存数据 , 如果没有在保存。

那么问题就出现了 , 我们传入的新增的参数肯定是不会带有主键id的,那么此时他根据id去查找key,而你的id是null,他就会报这个错误。

解决办法:

换成CachePut注解,因为这个注解不会先去查找,而是直接添加到缓存中,所以就不存在这个情况。

第二,使用的是CachePut,但还是报这个错误。

这个情况,肯定是因为你使用的是xxxDTO来接收前端的参数,而不是直接使用xxx的实体类来接受,这样就导致一个问题,就是前端传来的参数主键id肯定一开始也是null , 二主键的回显是在调用的mapper层之后才生成的,而错就错在,你是用xxx实体类对象来接收回显的主键,而不是xxxDTO这个参数对象,那么当整个方法执行完后,xxxDTO这个参数的id一直都是null,而注解是这样的:

复制代码
@CachePut(cacheNames = "dishCache" , key = "#dishDTO.id")

他是根据xxxDTO来获取id的,所以会报key为null。

解决办法:

当然,我们肯定不能直接换成实体类来接收前端传来的参数,因为毕竟可能有些属性实体类没有需要我们使用xxxDTO来接收。所以我们可以在主键回显后, 把主键赋值给xxxDTO就可以了,具体代码如下:

     /*
            为什么这里要多此一举给参数dishDTO赋值id呢?因为上面在使用springCache需要从dishDTO获取id生成key,
            但是dishDTO中的参数在这个方法执行完一直都是null , 主键回显只会回显在dish对象中的id。
            所以springCache得不到id就会报错 , 所以需要给dishDTO的id赋值。
         */
        dishDTO.setId(dish.getId());

二 报错:类型转换异常

这个问题一定是因为你存入数据的注解和取出数据的注解放在不一样的层的方法上。

最常见的是,你把CachePut方法放在Controller层的方法上,那么你存入的数据肯定是一个Result类型的数据。而你把Cacheable注解方法Server层方法上,那么该方法返回的肯定是一个xxx实体类,这就会导致,你存入的数据是一个Result类,而你需要取的数据又变成了xxx实体类,从而导致报错。

解决办法:

你可以全部放在Server层,或者全部放在Controller,只要确保你存入数据的方法的返回数据类型和你取出方法的返回数据类型一致就可以。

三 取出的数据为null

这个不用看,一定是因为你存入缓存的注解放在了一个返回为void的方法上面。

你只需要记住,springCache的注解,他的存入和取出的数据的类型一定是根据你的方法的返回值来的。如果你的返回值类型是void,那么他存入缓存的数据就是null,所以你取出来肯定也是null。

演示代码如下;

java 复制代码
 @CachePut(cacheNames = "dishCache" , key = "#dishDTO.id")
    @Override
    public void addDish(DishDTO dishDTO) {
//        向菜品表插入数据
        Dish dish = new Dish();
        BeanUtils.copyProperties(dishDTO , dish);
        dishMapper.addDish(dish);
//        因为下面的菜品口味表需要使用到菜品的id,所以这里菜品完成后,需要获取菜品id,再赋值给菜品口味
        Long dishId = dish.getId(); //但是这个id不能直接得到,需要在sql中使用主键回显,才能把生成的主键返回

        /*再根据菜品id,新增菜品口味表*/
//        取出集合数据
        List<DishFlavor> flavors = dishDTO.getFlavors();
        if (flavors!=null && flavors.size()>0){
//            这里需要遍历集合中每一个dishFlavor对象,把dishId赋值给他们
            flavors.forEach(dishFlavor -> {dishFlavor.setDishId(dishId);});
            dishFlavorMapper.addDishFlavor(flavors) ;
        }

        /*
            为什么这里要多此一举给参数dishDTO赋值id呢?因为上面在使用springCache需要从dishDTO获取id生成key,
            但是dishDTO中的参数在这个方法执行完一直都是null , 主键回显只会回显在dish对象中的id。
            所以springCache得不到id就会报错 , 所以需要给dishDTO的id赋值。
         */
        dishDTO.setId(dish.getId());
    }

取出的值如下:

解决方法:

把方法的返回值类型由viod改成对应的需要存储的数据的实体类型。

相关推荐
BergerLee9 小时前
对不经常变动的数据集合添加Redis缓存
数据库·redis·缓存
huapiaoy9 小时前
Redis中数据类型的使用(hash和list)
redis·算法·哈希算法
【D'accumulation】10 小时前
令牌主动失效机制范例(利用redis)注释分析
java·spring boot·redis·后端
Cikiss10 小时前
微服务实战——SpringCache 整合 Redis
java·redis·后端·微服务
一休哥助手11 小时前
Redis 五种数据类型及底层数据结构详解
数据结构·数据库·redis
盒马盒马12 小时前
Redis:zset类型
数据库·redis
Jay_fearless14 小时前
Redis SpringBoot项目学习
spring boot·redis
Wang's Blog14 小时前
Redis: 集群环境搭建,集群状态检查,分析主从日志,查看集群信息
数据库·redis
wclass-zhengge20 小时前
Redis篇(最佳实践)(持续更新迭代)
redis·缓存·bootstrap
Dylanioucn20 小时前
【分布式微服务云原生】探索Redis:数据结构的艺术与科学
数据结构·redis·分布式·缓存·中间件