记一次解决Null key returned for cache operation的过程

本文分享了如何在使用Spring Cache @Cacheable时,遇到空json导致的`Nullkeyreturnedforcacheoperation`问题,通过添加条件判断和预处理空值的方法来避免错误,并提供了代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

起因

在某个入参为map的方法上加了@Cacheable注解后,测试传入空json(在mapper业务逻辑里面传入空json是搜全表)时,报错:Null key returned for cache operation
网上查了各种解决方案,挺多都是说SPEL解析式解析key值出问题啥的,有点像是底层问题,而框架底层代码我一个小白是不敢动的,就非常抓狂。网上找到的的解决方法:

  • 改@Cacheable注解的入参为p1p2之类的
  • 给编译加-parameters参数的(不推荐)
  • 炫技类自己写key generator
    不过最后结合我自己的情况,加上同事的指导,以上的解决方案我都不需要
    我只需要在controller加一个数据预处理就好了。
    把我的解决过程发出来记录分享下~希望能帮助到跟我一样抓狂的小白

代码结构描述

Map<String, String> {//仅描述
	"XXX" : "xxx"
}
//Controller
public class XXXColtroller {
	public ControllerRetType getXXX (@RequestBody Map<String, String> map) {
		......
		ServiceRetType serviceRetVal = XXXService.getXXX(map);
		......
	}
}
//Service
public class XXXService {
	@Cacheable(value = "XXXCache", key = "#map[XXX]")//重要
	public ServiceRetType getXXX (Map<String, String> map) {
		......
		MapperRetType mapperRetVal = XXXMapper.getXXX(map);
		......
	}
}
<!-- XXXXMapper.xml中getXXX的sql描述   -->
<!-- sql逻辑:当XXX为null时,就会查全表   -->
<select id="getXXX" resultType = "java.util.HashMap"
parameterType = "java.util.HashMap">
	select * from XXTable a where 1 = 1
	<if  test="XXX != '' and XXX != null">
		AND a.XXX = #{XXX}
	</if>
</select>

Bug产生过程:Postman构造json测试

  • 当json含有 {“XXX” : “xxx”}时,可以顺利查出来,也能成功缓存,因为这个时候缓存的key (就是#map[XXX])是存在的。
  • 当json不含有"XXX"这个key时,如json={},本来要的效果是查全表,结果直接报错:Null key returned for cache operation

Bug原因分析

就如代码提供的错误信息:Null Key,service的入参map中根本没有"XXX"这个key,那自然就是null key。

如何解决?

方法1:绕开key为null的情况

仅需给上文的@Cacheable注解添加一个参数:

@Cacheable(value = "XXXCache", key = "#map[XXX]", condition = "#map[XXX] != null")

效果:当请求的map参数没有"XXX"这个key的时候(#map[XXX] = null),不走缓存,直接走数据库查询
不满足condition条件的情况,@Cacheable不会处理,那么就自然不会报错啦~

方法2:对空值做预处理

具体到本次情况,当入参map不含有"XXX"的key时,我们在Controller手动给它赋一个初值~
方法2相比方法1的好处在于,key为null时也可以缓存了,等于说所有状况都可以缓存。

public class XXXColtroller {
	public ControllerRetType getXXX (@RequestBody Map<String, String> map) {
		......
		map.putIfAbsent("XXX", "");//对空值做预处理
		ServiceRetType serviceRetVal = XXXService.getXXX(map);
		......
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值