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改成对应的需要存储的数据的实体类型。

相关推荐
虹科网络安全5 小时前
艾体宝产品|深度解读 Redis 8.4 新增功能:原子化 Slot 迁移(上)
数据库·redis·bootstrap
虹科网络安全8 小时前
艾体宝新闻|Redis 月度更新速览:2026 年 3 月
数据库·redis·缓存
y = xⁿ10 小时前
Redis八股学习日记:布隆过滤器
数据库·redis·学习
IT界的老黄牛12 小时前
停电后 Redis 集群两节点起不来:fix 完还报 Bad file format?多部分 AOF 修复的正确姿势
运维·redis·缓存
YaBingSec14 小时前
玄机网络安全靶场:Hadoop YARN ResourceManager 未授权 RCE WP
大数据·数据库·hadoop·redis·笔记·分布式·web安全
qq_40999093?14 小时前
NoSQL数据库解析:Redis
数据库·redis·nosql
KeyonY15 小时前
车联网规则引擎设计之热更新与版本管理
redis·golang·车联网
代码中介商15 小时前
Linux多线程编程完全指南(下):线程同步与互斥锁
linux·redis·线程·互斥锁
Lyyaoo.16 小时前
Session粘滞性问题->Redis实现session共享
数据库·redis·缓存
Mr_sst16 小时前
文件上传并发控制:为什么选Redisson可过期信号量?(避坑指南)
网络·数据库·redis·分布式·安全架构