Redis是否会将Long类型存储为Int?类型转换异常求助
问题分析与解决方案
核心问题解答
Redis本身不会主动将Long类型存储为Int——问题出在Jackson的反序列化逻辑上。
原因解析
你使用了GenericJackson2JsonRedisSerializer作为值序列化器,这个序列化器的特性是:当反序列化JSON数值时,如果数值落在Java Integer的取值范围内(-2147483648 到 2147483647),Jackson会自动将其解析为Integer对象,而非你期望的Long。但你的RedisTemplate泛型声明为RedisTemplate<String, Long>,调用get()方法时框架会尝试将实际的Integer对象强转为Long,直接触发ClassCastException。
解决方案
提供三种可行的解决方式,按需选择:
1. 强制指定Long类型的序列化器
替换GenericJackson2JsonRedisSerializer为Jackson2JsonRedisSerializer并明确指定类型,让Jackson始终按Long类型序列化/反序列化:
@Bean fun numericRedisTemplate(redisConnectionFactory: LettuceConnectionFactory): RedisTemplate<String, Long> { val template = RedisTemplate<String, Long>() template.connectionFactory = redisConnectionFactory template.keySerializer = StringRedisSerializer(Charsets.UTF_8) // 明确指定Long类型的序列化器 template.valueSerializer = Jackson2JsonRedisSerializer(Long::class.java) template.hashKeySerializer = StringRedisSerializer(Charsets.UTF_8) template.hashValueSerializer = Jackson2JsonRedisSerializer(Long::class.java) return template }
2. 显式转换数值类型
在获取值时主动转换类型,避免直接强转(Kotlin的扩展函数支持Integer和Long都调用toLong()):
fun getBalance(accountNumber: String): Long { val value = numericRedisTemplate.opsForValue().get(accountNumber) return value?.toLong() ?: -1L }
3. 启用Jackson类型信息存储
配置GenericJackson2JsonRedisSerializer保存类型元信息,让Jackson反序列化时能识别原始类型:
@Bean fun numericRedisTemplate(redisConnectionFactory: LettuceConnectionFactory): RedisTemplate<String, Long> { val template = RedisTemplate<String, Long>() // 配置带类型信息的序列化器 val serializer = GenericJackson2JsonRedisSerializer().apply { objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL) } template.connectionFactory = redisConnectionFactory template.keySerializer = StringRedisSerializer(Charsets.UTF_8) template.valueSerializer = serializer template.hashKeySerializer = StringRedisSerializer(Charsets.UTF_8) template.hashValueSerializer = serializer return template }
这种方式会在Redis存储的JSON中添加@class字段标记原始类型,确保反序列化时不会自动转换为Integer。
内容的提问来源于stack exchange,提问作者박수민
相关产品推荐
相关产品推荐

