MongoDB 字段中数据类型不一致序列化异常排查与处理

MongoDB 字段中数据类型不一致序列化异常排查与处理

背景如下,因为项目迁移愿意,一个使用Mongodb的业务拥有C#和Java两组Api。Java Api开发和测试都很顺利。上线一段时间后,客服反馈记录都不见了。查看数据库发现,时间字段拥有两种格式,其中一种是数组类型(如:[636693353404905287, 480]),另一种是日期类型(如:0001-01-01T00:00:00Z)

排查原因

首先看了原有C#代码的逻辑,使用的是DateTimeOffset类型存入的数据库。Java使用的是LocalDateTime类型。经过调用Api测试后,发现使用C#接口创建的数据,是数组格式。接下来就是在Java中对这个Document的序列化进行处理。

解决方案

首先看到[636693353404905287, 480],想到的就是时间戳,第二位应该保存的是时区。写了一个测试方法,将636693353404905287转为LocalDatetime,初步测试,将初始时间1901-01-01,时区偏移为480分钟。经过多种类型的测试,转化为了正确的时间(人工记忆创建记录的时间)。

知道了如何转化,就要在java解析时使用自定义的序列化器。

首先创建List转LocalDateTime的序列化器

import org.springframework.core.convert.converter.Converter;
import org.springframework.data.convert.ReadingConverter;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.List;/***** 包含如下格式脏数据,[636693353404905287, 480], 经测试是旧版c#接口导致的,并试验起始时间是"0001-01-01T00:00:00Z"* 并且此时间戳不需要进行时区转换*/
@ReadingConverter
public class ArrayListToLocalDateTimeConverter implements Converter<List<Object>, LocalDateTime> {@Overridepublic LocalDateTime convert(List<Object> source) {if (source.size() >= 2 && source.get(0) instanceof Long) {long timestamp = (Long) source.get(0);// 假设起始时间是"1601-01-01T00:00:00Z",请根据需要进行调整Instant startInstant = Instant.parse("0001-01-01T00:00:00Z");// 注意:原始时间戳可能需要根据实际情况调整计算方式Instant actualInstant = startInstant.plusMillis(timestamp / 10_000);return LocalDateTime.ofInstant(actualInstant, ZoneOffset.UTC);}throw new IllegalArgumentException("Invalid source for conversion: " + source);}
}

然后在MongoDB的配置类中注册

import com.mongodb.MongoClientURI;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.mongodb.MongoDbFactory;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.SimpleMongoDbFactory;
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
import org.springframework.data.mongodb.core.convert.MongoCustomConversions;import java.util.Arrays;@Configuration
public class MongoConfig {@Value("${spring.data.mongodb.uri}")private String uri;@Bean(name = "mongoTemplate")@Primarypublic MongoTemplate mongoTemplate() {MongoTemplate template = new MongoTemplate(mongoDbFactory());customizeMongoTemplate(template);return template;}@Bean@Primarypublic MongoDbFactory mongoDbFactory() {return new SimpleMongoDbFactory(new MongoClientURI(uri));}/*** 为了解决mongodb中的时间戳转换问题*/@Beanpublic MongoCustomConversions mongoCustomConversions() {return new MongoCustomConversions(Arrays.asList(new ArrayListToLocalDateTimeConverter()));}private void customizeMongoTemplate(MongoTemplate template) throws Exception {MappingMongoConverter converter = (MappingMongoConverter) template.getConverter();converter.setCustomConversions(mongoCustomConversions());converter.afterPropertiesSet();}}

uri:其中uri时从配置文件中读取的,mongo 的数据库连接。
mongoTemplate:注入MongoTemplate,用于操作数据库。
mongoCustomConversions:注入自定义的转换器,用于将数据库中的数据转换为Java中的数据。
customizeMongoTemplate:将自定义的转换器注入到MongoTemplate中。

这种是单数据源配置,如果要有多数据源,将MongoTemplate和MongoDbFactory复制,的注入名称修改为不同的名称即可。

总结

经过配置,如果类型是数组,则会触发进行解析。该字段正常的数据可以直接映射。

后续会将C#的流量转发到Java接口,然后将C#接口下线。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/669759.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java函数式接口:编程美学的革新之旅

1. 引言 函数式接口的概念 在Java中&#xff0c;函数式接口(Functional Interface)是一个关键的概念&#xff0c;它为Java的函数式编程提供了基础。一个函数式接口定义了一个具有单个抽象方法的接口&#xff0c;允许使用Lambda表达式或方法引用作为实例。这种接口的主要目的是…

uniapp 之 base64转临时地址播放mp3

需求是&#xff1a;进入页面的时候是先有背景音乐&#xff0c;发送问题请求回答的时候会返回文字和音频&#xff0c;前端要把音频读出来&#xff0c;并且把背景音乐停止&#xff0c;读完音频后再打开背景音乐 一开始用的直接base64直接拼接在地址后 真机放不了 const innerAu…

GCC编译器技巧--在C语言里面使用使用内敛汇编

GCC内敛汇编 基本格式 asm(汇编语句 :输出操作数(可选) :输入操作数(可选) :被破坏的寄存器(可选) );示例 int a 10, b; asm("movl %1, %%eax; movl %%eax, %0;":"r"(b) /*输出*/:"r"(a) /*输入*/:"%eax" /*破坏的寄存器*/)实现…

【RT-DETR有效改进】利用SENetV2重构化网络结构 (ILSVRC冠军得主,全网独家首发)

👑欢迎大家订阅本专栏,一起学习RT-DETR👑 一、本文介绍 本文给大家带来的改进机制是SENetV2,其是2023.11月的最新机制(所以大家想要发论文的可以在上面下点功夫),其是一种通过调整卷积网络中的通道关系来提升性能的网络结构。SENet并不是一个独立的网络模型,而…

Node.js JSON Schema Ajv依赖库逐步介绍验证类型和中文错误提示

在构建应用程序时&#xff0c;数据的有效性是至关重要的。为了确保传入的数据符合预期的格式和规范&#xff0c;我们可以使用 Ajv&#xff08;Another JSON Schema Validator&#xff09;进行验证。在这篇博文中&#xff0c;我们将从头开始学习 Ajv&#xff0c;逐步介绍验证类型…

【kafka】使用kafka client连接 kerberos认证的 kafka,scala版

注意keytab路径中不要使用\\&#xff0c;都使用/作为分隔符 使用kerberos需要配置jaas如下日志打印&#xff0c;两个配置至少设置一个&#xff1a; [DEBUG] org.apache.kafka.common.security.JaasContext:106 --- System property java.security.auth.login.config and Kafk…

Unity3D判断屏幕中某个坐标点的位置是否在指定UI区域内

系列文章目录 unity工具 文章目录 系列文章目录前言一、使用rect.Contains()判断1-1、转换坐标1-2、代码如下&#xff1a;1-3、注意事项1-3、测试效果如下 二、使用坐标计算在不在区域内2-1、方法如下&#xff1a;2-2、注意事项 三、使用RectTransformUtility.ScreenPointToLo…

2024-02-05 Linux shell 脚本检查检测某个环境变量是否已设置

一、这段脚本定义了一个函数check_config&#xff0c;用于检查传递给函数的环境变量或shell变量是否已设置&#xff08;即非空&#xff09;。如果所有变量都已设置&#xff0c;函数返回0&#xff08;成功&#xff09;&#xff1b;否则&#xff0c;它打印一条信息&#xff0c;指…

MongoDB从入门到实战之Docker快速安装MongoDB

前言 在上一篇文章中带领带同学们快速入门MongoDB这个文档型的NoSQL数据库&#xff0c;让大家快速的了解了MongoDB的基本概念。这一章开始我们就开始实战篇教程&#xff0c;为了快速把MongoDB使用起来我将会把MongoDB在Docker容器中安装起来作为开发环境使用。然后我这边MongoD…

SQL Server数据库日志查看若已满需要清理的三种解决方案

首先查看获取实例中每个数据库日志文件大小及使用情况&#xff0c;根据数据库日志占用百分比来清理 DBCC SQLPERF(LOGSPACE) 第一种解决方案&#xff1a; 在数据库上点击右键 → 选择 属性 → 选择 文件&#xff0c;然后增加数据库日志文件的文件大小。 第二种解决方案 手动…

宝塔+php+ssh+vscode+虚拟机 远程调试

远程(虚拟机)宝塔 安装扩展 配置文件添加&#xff0c;zend_extension看你虚拟机的具体位置 [Xdebug] zend_extension/www/server/php/74/lib/php/extensions/no-debug-non-zts-20190902/xdebug.so xdebug.modedebug xdebug.start_with_requesttrigger xdebug.client_host&quo…

gunicorn日志--access-logformat不起作用

使用gunicornsupervisor启动fastapi服务&#xff0c;命令如下&#xff1a; gunicorn main:app --workers 2 --worker-class uvicorn.workers.UvicornWorker --bind 127.0.0.1:8000 --access-logfile - 其中access log记录到的内容如下&#xff1a; 176.123.7.11:0 - "GE…

服务器与电脑的区别

1. PC机和专业服务器是完全是两种东西&#xff0c;硬件不同&#xff0c;当然驱动也不可能相同。比如说对服务器/工作站主板而言&#xff0c;最重要的 是高可靠性和稳定性&#xff0c;其次才是高性能。因为大多数的服务器都要满足每天24小时、每周7天的满负荷工作要求。价格方面…

C/C++ - 容器list

目录 容器特性 list 容器特性 使用场景 构造函数 默认构造函数 填充构造函数 范围构造函数 复制构造函数 大小函数 函数&#xff1a;size 函数&#xff1a;empty​ 函数&#xff1a;max_size​ 增加函数 函数&#xff1a;​push_back​ 函数&#xff1a;push_f…

车位检测,YOLOV8,OPENCV调用

车位检测YOLOV8NANO,opencv调用 车位检测&#xff0c;YOLOV8NANO&#xff0c;训练得到PT模型&#xff0c;然后转换成ONNX&#xff0c;OPENCV的DNN调用&#xff0c;支持C,PYTHON,ANDROID

行业知识图谱是什么

行业知识图谱是一种将行业知识从业务场景抽象到计算机可读的知识结构。它是指在行业内业务领域中&#xff0c;对各种业务实体、概念、属性以及关系的一种结构化描述。是一种通过知识表示、推理和查询的手段&#xff0c;将行业知识以图形化方式表示出来。它可以被用来建立企业的…

C#用Array类的FindAll方法和List<T>类的Add方法按关键词在数组中检索元素并输出

目录 一、使用的方法 1. Array.FindAll(T[], Predicate) 方法 &#xff08;1&#xff09;定义 &#xff08;2&#xff09;示例 2.List类的常用方法 &#xff08;1&#xff09;List.Add(T) 方法 &#xff08;2&#xff09;List.RemoveAt(Int32) 方法 &#xff08;3&…

Bytebase 签约 Vianova,助力欧洲城市交通智能平台中 Snowflake 和 PG 的变更自动化及版本控制

在数字化发展的浪潮中&#xff0c;自动化数据库变更管理成为提升产品上线效率、降低人为失误风险的关键工具&#xff0c;同时促进流程的一致性与标准化&#xff0c;确保合规性和变更的可追溯性。近日&#xff0c;数据库 DevOps 团队协同管理工具 Bytebase 签约欧洲交通数据管理…

免费在线绘图工具有哪些好用的?线画图工具是比较好的选择?

据说一张图胜过千言万语。一张好的图片可以帮助你快速表达自己的想法&#xff0c;让自己的想法更直观清晰&#xff0c;无论是产品分析、方案选项还是技术交流。市面上有很多绘图工具。这里有一些好用又免费的工具&#xff0c;绝对会让你在几分钟内坠入爱河。 即时设计 - 可实时…

Android~集成opencv问题

dlopen failed: library “libopencv_java4.so” not found E FATAL EXCEPTION: mainProcess: com.cv.monitor, PID: 4371java.lang.UnsatisfiedLinkError: dlopen failed: library "libopencv_java4.so" not found: needed by /data/app/~~KwL8rjD8_by_YVAyU82UCA…