@Cacheable缓存对象为空时遇到的坑

  • A+
所属分类:Java redis springboot 缓存

今天生产环境遇到@Cacheable的一个问题,记录一下

1、发现问题

接口突然请求失败,查询日志发现有如下报错

Cache 'cache:getCustRange' does not allow 'null' values. Avoid storing null via '@Cacheable(unless="#result == null")' or configure RedisCache to allow 'null' via RedisCacheConfiguration. java.lang.IllegalArgumentException: Cache 'cache:getCustRange' does not allow 'null' values. Avoid storing null via '@Cacheable(unless="#result == null")' or configure RedisCache to allow 'null' via RedisCacheConfiguration

日志提示信息说的很清楚,缓存中不允许存储null值,在@Cacheable中加上(unless="#result == null")

或者在RedisCacheConfiguration中配置成允许缓存中存储null值

下面来看一下有问题的代码

@Cacheable(cacheNames = "cache:getCustRange", key = "#root.args[0]['custId'] + ''")
  public CustRangeVo getCustRange(Map<String, Object> map) {
    return custMapper.getCustRange(map);
  }

很明显,是这里的CustRangeVo 对象为空了,保存到缓存时就报错了

2、解决问题

两种方法来解决这个问题

  • 设置结果为空时不缓存

  • 设置允许缓存为null值

设置结果为空时不缓存,直接加上unless="#result == null"就好了

@Cacheable(cacheNames = "cache:getCustRange", key = "#root.args[0]['custId'] + ''", unless="#result == null")
  public CustRangeVo getCustRange(Map<String, Object> map) {
    return custMapper.getCustRange(map);
  }

注意,我这里的场景是99.9%会查询到数据,极端情况下对象才会为空

假如你的大部分场景查询都为空,你不缓存空的话,会导致大部分请求命中数据库,你的缓存加的就没有意义了

设置允许缓存为null值 需要配置RedisCacheConfiguration,我们看一下源码

public void put(Object key, @Nullable Object value) {


发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: