Spring-data-redis @Cacheable java.lang.ClassCastException: java.util.LinkedHashMap 不能 cast to MyObject

2022-09-04 22:52:52

我正在使用spring-data-redis在我的spring Boot应用程序中缓存数据。我使用Mongo作为我的主数据源,Redis作为缓存。当我第一次点击API时,它从Mongo获取记录并将其保存在缓存中,并将MyObject正确返回给客户端。但是当我第二次点击API时,它会在缓存中找到记录,并且在尝试将其反序列化回MyObject时,它会。总是遇到强制转换异常:

java.lang.ClassCastException: java.util.LinkedHashMap 不能 cast 到 MyObject

这是我的 Redis 配置:

public class MyConfiguration {
    @Bean
    public CacheManager cacheManager(RedisTemplate<String, MyObject> redisTemplate) {
        return new RedisCacheManager(redisTemplate);
    }

    @Bean
    public RedisTemplate<String, MyObject> redisTemplate(RedisConnectionFactory connectionFactory, ObjectMapper objectMapper) {
        StringRedisSerializer serializer = new StringRedisSerializer();
        GenericJackson2JsonRedisSerializer hashValueSerializer = new GenericJackson2JsonRedisSerializer(objectMapper);
        RedisTemplate<String, MyObject> redisTemplate = new RedisTemplate<>();
        redisTemplate.setKeySerializer(serializer);
        redisTemplate.setValueSerializer(hashValueSerializer);
        redisTemplate.setConnectionFactory(connectionFactory);
        return redisTemplate;
    }
}

发现此处报告的相同问题:Spring-data-redis @Cacheable java.lang.ClassCastException:java.util.HashMap 无法转换为 java.lang.String

我研究了很长一段时间,但没有想法。请建议。提前感谢一吨。


答案 1

它为我工作,只需在键,值和,中设置一个新的参数。GenericJackson2JsonRedisSerializer()noserializerhash keyvalue serializer

@Bean
    public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory lettuceConnectionFactory, ObjectMapper objectMapper) {
        final RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>();
        redisTemplate.setConnectionFactory(lettuceConnectionFactory);
        // value serializer
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        // hash value serializer
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());

        logger.info("wiring up Redistemplate...");
        return redisTemplate;
    }

答案 2

原因

您已经自定义了 objectMapper,并且 Redis 值中没有类名。因此,它不能反序列化为真实类型。

您可以检查 redis 值,redis 值中没有“@class”:“com.xxxx.xxx.entity.xx”。

我的解决方案

@Bean
public RedisCacheConfiguration redisCacheConfiguration(ObjectMapper objectMapper) {
    // Do not change the default object mapper, we need to serialize the class name into the value
    objectMapper = objectMapper.copy();
    objectMapper = objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
    return RedisCacheConfiguration.defaultCacheConfig()
            .entryTtl(Duration.ofMinutes(1))
            .disableCachingNullValues()
            .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer(objectMapper)));
}

我使用深入研究GenericJackson2JsonRedisSerializer的源代码之后.classobjectMapper.enableDefaultTyping()


推荐