Spring Boot Redis缓存清除异常:无法将Category转换为String
问题解决:Redis缓存清除时的键转换异常
问题根源
你遇到的异常是因为@CacheEvict默认会将方法参数(这里是Category实体对象)作为缓存键,但当前Redis缓存配置仅配置了值的序列化,未配置键的转换器,也未给Category重写toString()方法,导致无法将对象转换为Redis所需的String类型键。
另外,你的listAll()方法缓存的是全部分类列表,它的缓存键是默认生成的(无参数时为SimpleKey.EMPTY),而persist()方法默认用Category对象当键去清除缓存,不仅删不到正确的缓存,还触发了键转换异常,且这个转换过程在执行@CacheEvict时就会触发,和缓存是否存在无关。
解决方案
方案一:统一指定缓存键(推荐)
给@Cacheable和@CacheEvict指定同一个固定键,确保清除的是全部分类列表的缓存:
修改服务层代码:
@CacheEvict(value = CacheConstants.CACHE_NAME_PREFIX + "categories", key = "'all_categories'") public Category persist(Category entity) { return repo.save(entity); } @Cacheable(value = CacheConstants.CACHE_NAME_PREFIX + "categories", key = "'all_categories'", unless = "#result == null") public List<Category> listAll() { return repo.findAll(); }
这里用固定字符串'all_categories'作为缓存键,避免了对象转键的问题,同时确保新增分类时能正确清除全部分类的缓存。
方案二:配置Redis键序列化器(适用于需用对象作为键的场景)
如果业务需要用对象作为缓存键,可以在缓存配置中添加键的序列化器,比如使用GenericToStringSerializer:
修改CacheConfig:
@Bean public RedisCacheConfiguration cacheConfiguration() { return RedisCacheConfiguration.defaultCacheConfig() .entryTtl(Duration.ofMinutes(properties.getCache().getRedisCacheEntryTtl())) .disableCachingNullValues() // 配置键的序列化器 .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericToStringSerializer<>(Object.class))) .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer())); }
但此方案不适用于当前场景,因为我们需要清除的是全部分类列表的缓存,而非单个Category的缓存。
内容的提问来源于stack exchange,提问作者Hani Bikdeli
相关产品推荐
相关产品推荐

