Null key returned for cache operation(maybe you are using named params on classes without debug info

在使用@Cacheable注解的时候遇到的这个问题

@Cacheable(value = RedisConstant.USER, key = "#id")
UserShow userShow(String id);

奇怪的是本地从没遇到过,生产上也是偶尔遇到,而@Cacheable注解肯定支持key属性,查看日志也没找到原因,最终在网上的一篇文章里面看到和debug模式有关,反射无法获取到参数值。

进入日志打印的类里面看一下:

private Object generateKey(CacheOperationContext context, @Nullable Object result) {
	Object key = context.generateKey(result);
	if (key == null) {
		throw new IllegalArgumentException("Null key returned for cache operation (maybe you are " +
				"using named params on classes without debug info?) " + context.metadata.operation);
	}
	if (logger.isTraceEnabled()) {
		logger.trace("Computed cache key '" + key + "' for operation " + context.metadata.operation);
	}
	return key;
}

好吧不管怎样,是由于context.generateKey(result);取不到值造成的,然而本地可以debug就不会遇到这个问题,生产上无法debug就会遇到???

两种解决方式:

  • 使用#p0
    在我理解中和MyBatisparam0类似?不使用反射查找出参数名,直接指定第一个参数,反正我一般不使用这个方法。

  • 自定义keyGenerator
    https://docs.spring.io/spring/docs/current/spring-framework-reference/integration.html#cache-annotations-cacheable
    Redis配置类中注入bean

    @Bean(name = "idGenerator")
    public KeyGenerator idGenerator() {
    	return new KeyGenerator() {
    		@Override
    		public Object generate(Object target, Method method, Object... params) {
    			StringBuilder sb = new StringBuilder();
    			sb.append(params[0].toString());
    			return sb.toString();
    		}
    	};
    }
    

    注意我这里使用的是idGenerator,而我在使用的时候接口参数中一般只有id字段,如果有其他的可以参考上面的链接自行配置。
    接口注解重写:

    @Cacheable(value = RedisConstant.USER, keyGenerator = "idGenerator")
    UserShow userShow(String id);
    

问题解决,目前没再遇到过这个问题。

你可能感兴趣的:(Bug问题,redis,Cacheable,keyGenerator)