当前位置: 首页 > news >正文

关于Redis-存Long取Integer类型转换错误的问题

背景

最近遇到了两个Redis相关的问题,趁着清明假期,梳理整理。

1.存入Long类型对象,在代码中使用Long类型接收,结果报类型转换错误。

2.String对象的反序列化问题,直接在Redis服务器上新增一个key-value,而后在代码中get(key)时,报反序列化失败。
关于Long类型转换错误
Redis的配置如下

Redis中序列化相关的配置,我这里采用的是GenericJackson2JsonRedisSerializer类型的序列化方式(这种方式会有一个类型转换的坑,下面会提到)

    @Configuration
    @AutoConfigureAfter(RedisAutoConfiguration.class)
    public class RedisConfiguration {
     
        @Bean
        public RedisTemplate<String, Object> redisTemplate(JedisConnectionFactory redisConnectionFactory) {
            RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
            redisTemplate.setConnectionFactory(redisConnectionFactory);
            redisTemplate.setKeySerializer(new StringRedisSerializer());
            redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
            redisTemplate.setHashKeySerializer(new StringRedisSerializer());
            redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
            redisTemplate.afterPropertiesSet();
            return redisTemplate;
        }
    }  


存入Long对象取出Integer对象

测试方法如下

    @Test
    public void redisSerializerLong(){
        try {
            Long longValue = 123L;
            redisLongCache.set("cacheLongValue",longValue);
            Object cacheValue = redisLongCache.get("cacheLongValue");
            Long a = (Long) cacheValue;
        }catch (ClassCastException e){
            e.printStackTrace();
        }
    }


会报类型转换错误java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.Long。

为什么类型会变为Integer呢?跟我一起追踪源码,便会发现问题。

1. 在代码的最外层获取redis中key对应的value值

redisTemplate.opsForValue().get(key);

2.在DefaultValueOperations类中的get(Object key)方法

    public V get(Object key) {
     
        return execute(new ValueDeserializingRedisCallback(key) {
     
            @Override
            protected byte[] inRedis(byte[] rawKey, RedisConnection connection) {
                return connection.get(rawKey);
            }
        }, true);
    }


3.打断点继续往里跟,RedisTemplate中的execute(RedisCallback<T> action, boolean exposeConnection, boolean pipeline)方法里面,有一行关键代码。

T result = action.doInRedis(connToExpose); 

此为获取redis中对应的value值,并对其进行反序列化操作。

4.在抽象类AbstractOperations<K, V>中,定义了反序列化操作,对查询结果result进行反序列化。

    public final V doInRedis(RedisConnection connection) {
        byte[] result = inRedis(rawKey(key), connection);
        return deserializeValue(result);
    }


V deserializeValue(byte[] value)反序列化

    V deserializeValue(byte[] value) {
        if (valueSerializer() == null) {
            return (V) value;
        }
        return (V) valueSerializer().deserialize(value);
    }


 5.终于到了具体实现类GenericJackson2JsonRedisSerializer

    public Object deserialize(@Nullable byte[] source) throws SerializationException {
        return deserialize(source, Object.class);
    }


实现反序列化方法,注意!这里统一将结果反序列化为Object类型,所以这里便是问题的根源所在,对于数值类型,取出后统一转为Object,导致泛型类型丢失,数值自动转为了Integer类型也就不奇怪了。

    public <T> T deserialize(@Nullable byte[] source, Class<T> type) throws SerializationException {
     
        Assert.notNull(type,
                "Deserialization type must not be null! Pleaes provide Object.class to make use of Jackson2 default typing.");
     
        if (SerializationUtils.isEmpty(source)) {
            return null;
        }
     
        try {
            return mapper.readValue(source, type);
        } catch (Exception ex) {
            throw new SerializationException("Could not read JSON: " + ex.getMessage(), ex);
        }
    }  


String对象转义问题 

测试方法

    @Test
    public void redisSerializerString() {
        try {
            String stringValue = "abc";
            redisStringCache.set("codeStringValue", stringValue);
            String cacheValue = redisStringCache.get("codeStringValue");     // 序列化失败
            String serverInsert = redisStringCache.get("serverInsertValue");
            if (Objects.equals(cacheValue, serverInsert)) {
                System.out.println("serializer ok");
            } else {
                System.out.println("serializer err");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


提前在redis服务器上插入一个非Json格式的String对象

直接在Redis服务器上使用set命令新增一对Key-Value,在代码中取出会反序列化失败, 

    org.springframework.data.redis.serializer.SerializationException: Could not read JSON: Unrecognized token 'abc': was expecting ('true', 'false' or 'null')
     at [Source: (byte[])"abc"; line: 1, column: 7]; nested exception is com.fasterxml.jackson.core.JsonParseException: Unrecognized token 'abc': was expecting ('true', 'false' or 'null')
     at [Source: (byte[])"abc"; line: 1, column: 7]
        at org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer.deserialize(GenericJackson2JsonRedisSerializer.java:132)
        at org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer.deserialize(GenericJackson2JsonRedisSerializer.java:110)
        at org.springframework.data.redis.core.AbstractOperations.deserializeValue(AbstractOperations.java:334)
        at org.springframework.data.redis.core.AbstractOperations$ValueDeserializingRedisCallback.doInRedis(AbstractOperations.java:60)
        at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:224)
        at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:184)
        at org.springframework.data.redis.core.AbstractOperations.execute(AbstractOperations.java:95)
        at org.springframework.data.redis.core.DefaultValueOperations.get(DefaultValueOperations.java:48)  


小总结

这个问题是因为,自己在测试的过程中,没有按照代码流程执行,想当然的认为,代码跑出来的结果和自己手动插入的结果是一样的。

在相关的测试验证过程中应该严格的控制变量,不能凭借下意识的决断来操作,谨记软件之事——必作于细!
————————————————

相关文章:

关于Redis-存Long取Integer类型转换错误的问题

背景 最近遇到了两个Redis相关的问题&#xff0c;趁着清明假期&#xff0c;梳理整理。 1.存入Long类型对象&#xff0c;在代码中使用Long类型接收&#xff0c;结果报类型转换错误。 2.String对象的反序列化问题&#xff0c;直接在Redis服务器上新增一个key-value&#xff0c…...

设计模式一:简单工厂模式(Simple Factory Pattern)

简单工厂模式&#xff08;Simple Factory Pattern&#xff09;是一种创建型设计模式&#xff0c;它提供了一个通用的接口来创建各种不同类型的对象&#xff0c;而无需直接暴露对象的创建逻辑给客户端。 简单工厂的三个重要角色&#xff1a; 工厂类&#xff08;Factory Class&…...

如何利用plotly和geopandas根据美国邮政编码(Zip-Code)绘制美国地图

对于我自己来说&#xff0c;该需求源自于分析Movielens-1m数据集的用户数据&#xff1a; UserID::Gender::Age::Occupation::Zip-code 1::F::1::10::48067 2::M::56::16::70072 3::M::25::15::55117 4::M::45::7::02460 5::M::25::20::55455 6::F::50::9::55117我希望根据Zip-…...

ceph集群搭建

文章目录 理论知识具体操作搭建ceph本地源yum源及ceph的安装配置NTP&#xff08;解决时间同步问题&#xff09;部署ceph自定义crush 理论知识 Ceph是一个分布式存储系统&#xff0c;并且提供了文件、对象、块存储功能。 Ceph集群中重要的守护进程有&#xff1a;Ceph OSD、Cep…...

前端密码加密 —— bcrypt、MD5、SHA-256、盐

&#x1f414; 前期回顾悄悄告诉你&#xff1a;前端如何获取本机IP&#xff0c;轻松一步开启网络探秘之旅_彩色之外的博客-CSDN博客前端获取 本机 IP 教程https://blog.csdn.net/m0_57904695/article/details/131855907?spm1001.2014.3001.5501 在前端密码加密方案中&#xff…...

汽车UDS诊断深度学习专栏

1.英文术语 英文术语翻译Diagnostic诊断Onboard Diagnostic 在线诊断 Offboard Diagnostic离线诊断Unified diagnostic service简称 UDS 2.缩写表 缩写解释ISO国际标准化组织UDSUnified diagnostic service&#xff0c;统一的诊断服务ECU电控单元DTC 诊断故障码 ISO14229UD…...

macOS 下安装brew、nvm

1、brew&#xff1a; /bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)" brew -v 查看版本 示例&#xff1a; 安装jdk brew search jdk 查询可用的jdk版本 brew install openjdk11 安装制定版本jdk 更换源&#xff1…...

【云原生】Kubernetes工作负载-StatefulSet

StatefulSet StatefulSet 是用来管理有状态应用的工作负载 API 对象 StatefulSet 用来管理某 Pod 集合的部署和扩缩&#xff0c; 并为这些 Pod 提供持久存储和持久标识符 和 Deployment 类似&#xff0c; StatefulSet 管理基于相同容器规约的一组 Pod。但和 Deployment 不同…...

Java:方法的重载

方法重载 为什么需要方法重载 在使用方法的过程中我们可能会遇到以下如同例子的情形&#xff1a; ​ ​ public class method1 {public static void main(String[] args) {int a1 10;int b1 20;double ret1 add(a1, b1);System.out.println("ret1 " ret1);do…...

7.react useCallback与useMemo函数使用与常见问题

react useCallback与useMemo函数使用与常见问题 useCallback返回一个可记忆的函数&#xff0c;useMemo返回一个可记忆的值&#xff0c;useCallback只是useMemo的一种特殊形式。 那么这到底是什么意思呢&#xff1f;实际上我们在父子通信的时候&#xff0c;有可能传递的值是一…...

Sentinel限流中间件

目录 介绍 Sentinel 的特征 Sentinel 的组成 实战使用 简单实例 配置本地控制台 使用可视化ui配置简单流控 配置异步任务限流 使用注解定义限流资源 SpringCloud整合Sentinel 简单整合 并发线程流控 关联模式 整合openFeign使用 介绍 随着微服务的流行&#xff0…...

使用ajax进行前后端交互的方法

使用ajax进行前后端交互的方法&#xff1a;&#xff08;我只测试通了json对象作为参数的方式&#xff0c;其他方式我没有测试通过&#xff09; 1、前端方法&#xff1a; 传参方式&#xff1a;POST 请求类型&#xff1a;json对象 响应类型&#xff1a;json对象 function test() …...

动手学深度学习——线性回归从零开始

生成数据集synthetic_data()读取数据集data_iter()初始化模型参数w, b定义模型&#xff1a;线性回归模型linreg()定义损失函数&#xff1a;均方损失squared_loss()定义优化算法&#xff1a;梯度下降sgd()进行训练&#xff1a;输出损失loss和估计误差 %matplotlib inline impor…...

Redis缓存击穿

Redis缓存击穿是指在使用Redis作为缓存时&#xff0c;某个热点数据过期或不存在&#xff0c;导致大量请求直接打到后端存储系统&#xff08;例如数据库&#xff09;&#xff0c;使得后端系统压力骤增&#xff0c;性能下降的情况。这种情况通常发生在热点数据失效的瞬间。 缓存…...

网络安全(黑客)自学的一些建议

1.选择方向 首先是选择方向的问题&#xff0c;网络安全是一个很宽泛的专业&#xff0c;包含的方向特别多。比如 web安全&#xff0c;系统安全&#xff0c;无线安全 &#xff0c;二进制安全&#xff0c;运维安全&#xff0c;渗透测试&#xff0c;软件安全&#xff0c;IOT安全&a…...

全志F1C200S嵌入式驱动开发(基于usb otg的spi-nor镜像烧入)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】 前面既然已经搞定了spi-nor驱动,那么下一步考虑的就是怎么从spi-nor flash上面加载uboot、kernel和rootfs。目前spi-nor就是一块白片,上面肯定什么都没有,那么这个时候,我们要做…...

如何恢复损坏/删除的 Word 文件

有关如何修复不可读的 Microsoft Word 文件或 Rich Text 文件中的文本的分步说明。这些说明有助于从损坏的*.doc、*.docx、*.dot、*.dotx、*.rtf文件&#xff08;任何版本和大小&#xff09;中提取文本&#xff0c;只需单击几下&#xff1a; 从此处下载奇客数据恢复 &#xff…...

【论文阅读】Feature Inference Attack on Shapley Values

摘要 研究背景 近年来&#xff0c;解释性机器学习逐渐成为一个热门的研究领域。解释性机器学习可以帮助我们理解机器学习模型是如何进行预测的&#xff0c;它可以提高模型的可信度和可解释性。Shapley值是一种解释机器学习模型预测结果的方法&#xff0c;它可以计算每个特征对…...

TDesign 中后台系统搭建

目录 1 模板安装2 启动项目3 添加页面总结 一般如果希望开发小程序&#xff0c;是要给使用的用户提供一套中后台系统来管理数据的。现在中后台系统开源项目也比较多&#xff0c;本篇我们介绍一个腾讯开源的TDesign模板。 1 模板安装 先要在电脑里安装好nodejs&#xff0c;搜索…...

Android 实现阅读用户协议的文字控件效果

开发中&#xff0c;经常要用到一些阅读隐私协议的场景&#xff0c;原生的textview控件很难做到在一个控件里有两个点击事件&#xff0c;那现在就来安利一个强大的组件——SpannableStringBuilder。 先看看效果&#xff1a; 直接上代码&#xff0c;布局文件&#xff1a; <Li…...

Spring Cloud AWS 实战教程:构建高可用 SQS 消息队列应用 [特殊字符]

Spring Cloud AWS 实战教程&#xff1a;构建高可用 SQS 消息队列应用 &#x1f680; 【免费下载链接】spring-cloud-aws The New Home for Spring Cloud AWS 项目地址: https://gitcode.com/gh_mirrors/sp/spring-cloud-aws Spring Cloud AWS 是一个强大的开源框架&…...

Python基础语法:访问器@property和修改器@xxx.setter

一、简介 访问器和修改器也是装饰器的一种。 property: 访问器&#xff0c;getter xxx.setter: 修改器&#xff0c;setter 访问器和修改器的根本目的是想将属性私有化&#xff0c;提供getter&setter去访问。 访问器和修改器能够做到访问属性其实在调用getter方法&#xff0…...

DISMTools企业部署:在组织中大规模应用的最佳实践

DISMTools企业部署&#xff1a;在组织中大规模应用的最佳实践 【免费下载链接】DISMTools The connected place for Windows system administration 项目地址: https://gitcode.com/GitHub_Trending/di/DISMTools DISMTools是一款专为Windows系统管理设计的连接平台&…...

照着用就行:2026 最新降AIGC软件测评与推荐

2026年真正好用的AI论文降重与改写工具&#xff0c;核心看降重效果、去AI味、格式保留、学术适配四大指标。综合实测&#xff0c;千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队&#xff0c;覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。 …...

我靠这个测试设计方法,把漏测率降低了80%

当“直觉测试”撞上南墙很长一段时间里&#xff0c;我和许多测试同行一样&#xff0c;测试用例的设计主要依靠两样东西&#xff1a;需求文档和“测试直觉”。这种模式在业务逻辑相对简单、迭代速度平缓时还能勉强应付。一旦面对复杂的企业级应用、高频的敏捷迭代&#xff0c;或…...

神经网络与深度学习 第3周课程总结

深度学习视觉应用课程总结 一、常用计算机视觉数据集数据集名称发布方/年份规模图像规格类别数主要用途核心特点MNIST美国国家标准与技术研究院60k训练10k测试2828灰度图10类(0-9手写数字)入门级图像分类最经典的手写数字识别基准数据集Fashion-MNISTZalando(2017)60k训练10k测…...

基于GSM与Arduino的远程控制系统:DIY电话控制与短信报警方案

1. 项目概述与核心价值如果你曾经想过&#xff0c;在离家几十公里外&#xff0c;仅凭一部普通的手机&#xff0c;就能远程打开家里的车库门、查看门窗是否关好&#xff0c;甚至在异常情况发生时让系统自动打电话给你报警&#xff0c;那么这个基于GSM的远程控制系统项目&#xf…...

如何让旧款Mac运行最新系统:OpenCore Legacy Patcher完整指南

如何让旧款Mac运行最新系统&#xff1a;OpenCore Legacy Patcher完整指南 【免费下载链接】OpenCore-Legacy-Patcher Experience macOS just like before 项目地址: https://gitcode.com/GitHub_Trending/op/OpenCore-Legacy-Patcher 想让你的老旧Mac设备重新焕发活力&a…...

音乐解锁工具:让加密音乐文件在任何设备自由播放

音乐解锁工具&#xff1a;让加密音乐文件在任何设备自由播放 【免费下载链接】unlock-music 在浏览器中解锁加密的音乐文件。原仓库&#xff1a; 1. https://github.com/unlock-music/unlock-music &#xff1b;2. https://git.unlock-music.dev/um/web 项目地址: https://gi…...

D3KeyHelper终极指南:5分钟掌握暗黑3最强自动化工具

D3KeyHelper终极指南&#xff1a;5分钟掌握暗黑3最强自动化工具 【免费下载链接】D3keyHelper D3KeyHelper是一个有图形界面&#xff0c;可自定义配置的暗黑3鼠标宏工具。 项目地址: https://gitcode.com/gh_mirrors/d3/D3keyHelper D3KeyHelper是一款专为《暗黑破坏神3…...