- A+
今天生产环境遇到@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) {