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

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#接口下线。

相关文章:

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

MongoDB 字段中数据类型不一致序列化异常排查与处理 背景如下&#xff0c;因为项目迁移愿意&#xff0c;一个使用Mongodb的业务拥有C#和Java两组Api。Java Api开发和测试都很顺利。上线一段时间后&#xff0c;客服反馈记录都不见了。查看数据库发现&#xff0c;时间字段拥有两…...

网络安全简介

网络安全&#xff1a; ​ 网络安全攻击分为被动攻击和主动攻击。 1. 被动攻击&#xff1a;是指攻击者从网络上窃取了他人的通信内容&#xff0c;通常把这类的攻击称为截获&#xff0c;被动攻击只要有2种形式&#xff1a;消息内容泄漏攻击和流量分析攻击。由于攻击者没…...

【Docker】.NET Core 6.0 webapi 发布上传到Docker Desktop并启动运行访问,接口返回数据乱码解决方法

欢迎来到《小5讲堂》&#xff0c;大家好&#xff0c;我是全栈小5。 这是《Docker容器》系列文章&#xff0c;每篇文章将以博主理解的角度展开讲解&#xff0c; 特别是针对知识点的概念进行叙说&#xff0c;大部分文章将会对这些概念进行实际例子验证&#xff0c;以此达到加深对…...

【Android Gradle 插件】自定义 Gradle 插件模块 ⑤ ( 完整总结 )

一、创建自定义插件类型模块 ( Java or Kotlin Library ) 选择 " 菜单栏 / New / New Module… " 选项 , 在 " Create New Module " 对话框中 , 选择 创建 " Java or Kotlin Library " 类型的依赖库 ; 二、手动导入相关依赖 ( Java | Groovy | …...

浅析现代计算机启动流程

文章目录 前言启动流程概述磁盘分区格式MBR磁盘GPT磁盘隐藏分区 传统BIOS引导传统BIOS启动流程 UEFI引导UEFI引导程序UEFI启动流程 引导加载程序启动操作系统相关参考 前言 现代计算机的启动是一个漫长的流程&#xff0c;这个流程中会涉及到各种硬件的配置与交互&#xff0c;包…...

七月论文审稿GPT第2.5和第3版:分别微调GPT3.5、Llama2 13B以扩大对GPT4的优势

前言 自去年7月份我带队成立大模型项目团队以来&#xff0c;我司至今已有5个项目组&#xff0c;其中 第一个项目组的AIGC模特生成系统已经上线在七月官网第二项目组的论文审稿GPT则将在今年3 4月份对外上线发布第三项目组的RAG知识库问答第1版则在春节之前已就绪至于第四、第…...

Android Studio导入项目 下载gradle很慢或连接超时

AS最常见的问题之一就是下载gradle非常慢&#xff0c;还经常出现下载失败的情况&#xff0c;没有gradle就无法build项目&#xff0c;所以一定要先解决gradle的下载问题&#xff0c;下面教大家两种常用方法 手动下载压缩包并替换 1、关闭Android Studio&#xff0c;复制下面的网…...

如何使用VSCode上运行Jupyter,详细案例过程出可视化图

Python作为最受AI喜欢的语言之一&#xff0c;我们与大家共同学习下如何在VS Code上运行Jupyter&#xff0c;并且用简单案例实现出图。 环境 VS Code version: 1.80.1 Python: 3.12.0 小白安装过程&#xff1a; 在准备好基础环境&#xff0c;小白心想&#xff0c;AI可是霸占科…...

Linux中有名管道和无名管道

无名管道基础 进程间通信介绍 常用通信方式 无名管道&#xff08;pipe&#xff09; 有名管道 &#xff08;fifo&#xff09; 信号&#xff08;signal&#xff09; 共享内存(mmap) 套接字&#xff08;socket&#xff09;过时的IPC通信方式 System V IPC 共享内存&#xff08;sh…...

[SWPUCTF 2021 新生赛]easyupload1.0

发现是上传文件第一想到是文件木马 <?php eval ($_POST[123]);?>木马上传burp修改后缀发现flag里面这个是假的 我们猜想是在phpinfo我们上传<?php eval(phpinfo(););?>木马上传burp修改后缀里面 CtrlF 发现flag...

【Linux网络编程三】Udp套接字编程(简易版服务器)

【Linux网络编程三】Udp套接字编程(简易版服务器&#xff09; 一.创建套接字二.绑定网络信息1.构建通信类型2.填充网络信息①网络字节序的port②string类型的ip地址 3.最终绑定 三.读收消息1.服务器端接收消息recvfrom2.服务器端发送消息sendto3.客户端端发送消息sendto4.客户端…...

【Rust】字符串,看这篇就够了

这节课我们把字符串单独拿出来讲&#xff0c;是因为字符串太常见了&#xff0c;甚至有些应用的主要工作就是处理字符串。比如 Web 开发、解析器等。而 Rust 里的字符串内容相比于其他语言来说还要多一些。是否熟练掌握 Rust 的字符串的使用&#xff0c;对 Rust 代码开发效率有很…...

单片机和 ARM 的区别

单片机和 ARM 在功能和使用上有一些区别&#xff0c;因此哪个更好用取决于具体的需求和场景。 单片机是一种集成了微处理器、存储器和外设接口的集成电路芯片&#xff0c;通常具有体积小、功耗低、可靠性高、成本低等特点。单片机广 泛应用于各种领域&#xff0c;如智能仪表、工…...

JavaScript从入门到精通系列第三十一篇:详解JavaScript中的字符串和正则表达式相关的方法

文章目录 知识回顾 1&#xff1a;概念回顾 2&#xff1a;正则表达式字面量 一&#xff1a;字符串中正则表达式方法 1&#xff1a;split 2&#xff1a;search 3&#xff1a;match 4&#xff1a;replace 知识回顾 1&#xff1a;概念回顾 正则表达式用于定义一些字符串的…...

23、数据结构/查找相关练习20240205

一、请编程实现哈希表的创建存储数组{12,24,234,234,23,234,23},输入key查找的值&#xff0c;实现查找功能。 代码&#xff1a; #include<stdlib.h> #include<string.h> #include<stdio.h> #include<math.h> typedef struct Node {int data;struct n…...

【VSTO开发-WPS】下调试

重点2步&#xff1a; 1、注册表添加 Windows Registry Editor Version 5.00[HKEY_CURRENT_USER\Software\kingsoft\Office\WPP\AddinsWL] "项目名称"""2、visual studio 运行后&#xff0c;要选中附加到调试&#xff0c;并指定启动项目。 如PPT输入WPP搜…...

git 的基本概念

当使用Git时&#xff0c;一些基本概念包括&#xff1a; 1. **仓库&#xff08;Repository&#xff09;&#xff1a;** 存储项目文件和版本历史的地方。可以是本地仓库&#xff08;在你的计算机上&#xff09;或远程仓库&#xff08;在服务器上&#xff09;。 2. **提交&#…...

《统计学习方法:李航》笔记 从原理到实现(基于python)-- 第6章 逻辑斯谛回归与最大熵模型(1)6.1 逻辑斯谛回归模型

文章目录 第6章 逻辑斯谛回归与最大熵模型6.1 逻辑斯谛回归模型6.1.1 逻辑斯谛分布6.1.2 二项逻辑斯谛回归模型6.1.3 模型参数估计6.1.4 多项逻辑斯谛回归 《统计学习方法&#xff1a;李航》笔记 从原理到实现&#xff08;基于python&#xff09;-- 第3章 k邻近邻法 《统计学习…...

Go 中如何检查文件是否存在?可能产生竞态条件?

嗨&#xff0c;大家好&#xff01;本文是系列文章 Go 技巧第十三篇&#xff0c;系列文章查看&#xff1a;Go 语言技巧。 Go 中如何检查文件是否存在呢&#xff1f; 如果你用的是 Python&#xff0c;可通过标准库中 os.path.exists 函数实现。遗憾的是&#xff0c;Go 标准库没有…...

红日靶场1搭建渗透

环境搭建 下载好镜像文件并解压&#xff0c;启动vmware 这里我用自己的win7 sp1虚拟机作为攻击机&#xff0c;设置为双网卡NAT&#xff0c;vm2 其中用ipconfig查看攻击机ip地址 设置win7 x64为双网卡&#xff0c;vm1&#xff0c;vm2 设置win08单网卡vm1&#xff0c;win2k3为单…...

脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)

一、数据处理与分析实战 &#xff08;一&#xff09;实时滤波与参数调整 基础滤波操作 60Hz 工频滤波&#xff1a;勾选界面右侧 “60Hz” 复选框&#xff0c;可有效抑制电网干扰&#xff08;适用于北美地区&#xff0c;欧洲用户可调整为 50Hz&#xff09;。 平滑处理&…...

(十)学生端搭建

本次旨在将之前的已完成的部分功能进行拼装到学生端&#xff0c;同时完善学生端的构建。本次工作主要包括&#xff1a; 1.学生端整体界面布局 2.模拟考场与部分个人画像流程的串联 3.整体学生端逻辑 一、学生端 在主界面可以选择自己的用户角色 选择学生则进入学生登录界面…...

Java多线程实现之Callable接口深度解析

Java多线程实现之Callable接口深度解析 一、Callable接口概述1.1 接口定义1.2 与Runnable接口的对比1.3 Future接口与FutureTask类 二、Callable接口的基本使用方法2.1 传统方式实现Callable接口2.2 使用Lambda表达式简化Callable实现2.3 使用FutureTask类执行Callable任务 三、…...

【7色560页】职场可视化逻辑图高级数据分析PPT模版

7种色调职场工作汇报PPT&#xff0c;橙蓝、黑红、红蓝、蓝橙灰、浅蓝、浅绿、深蓝七种色调模版 【7色560页】职场可视化逻辑图高级数据分析PPT模版&#xff1a;职场可视化逻辑图分析PPT模版https://pan.quark.cn/s/78aeabbd92d1...

Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析

Java求职者面试指南&#xff1a;Spring、Spring Boot、MyBatis框架与计算机基础问题解析 一、第一轮提问&#xff08;基础概念问题&#xff09; 1. 请解释Spring框架的核心容器是什么&#xff1f;它在Spring中起到什么作用&#xff1f; Spring框架的核心容器是IoC容器&#…...

AI+无人机如何守护濒危物种?YOLOv8实现95%精准识别

【导读】 野生动物监测在理解和保护生态系统中发挥着至关重要的作用。然而&#xff0c;传统的野生动物观察方法往往耗时耗力、成本高昂且范围有限。无人机的出现为野生动物监测提供了有前景的替代方案&#xff0c;能够实现大范围覆盖并远程采集数据。尽管具备这些优势&#xf…...

Linux nano命令的基本使用

参考资料 GNU nanoを使いこなすnano基础 目录 一. 简介二. 文件打开2.1 普通方式打开文件2.2 只读方式打开文件 三. 文件查看3.1 打开文件时&#xff0c;显示行号3.2 翻页查看 四. 文件编辑4.1 Ctrl K 复制 和 Ctrl U 粘贴4.2 Alt/Esc U 撤回 五. 文件保存与退出5.1 Ctrl …...

uniapp 字符包含的相关方法

在uniapp中&#xff0c;如果你想检查一个字符串是否包含另一个子字符串&#xff0c;你可以使用JavaScript中的includes()方法或者indexOf()方法。这两种方法都可以达到目的&#xff0c;但它们在处理方式和返回值上有所不同。 使用includes()方法 includes()方法用于判断一个字…...

从 GreenPlum 到镜舟数据库:杭银消费金融湖仓一体转型实践

作者&#xff1a;吴岐诗&#xff0c;杭银消费金融大数据应用开发工程师 本文整理自杭银消费金融大数据应用开发工程师在StarRocks Summit Asia 2024的分享 引言&#xff1a;融合数据湖与数仓的创新之路 在数字金融时代&#xff0c;数据已成为金融机构的核心竞争力。杭银消费金…...

Vite中定义@软链接

在webpack中可以直接通过符号表示src路径&#xff0c;但是vite中默认不可以。 如何实现&#xff1a; vite中提供了resolve.alias&#xff1a;通过别名在指向一个具体的路径 在vite.config.js中 import { join } from pathexport default defineConfig({plugins: [vue()],//…...