seata:mysql驱动8.0时,JacksonUndoLogParser 反序列化报错
seata1.4.1版本下
在使用mysql驱动8.0时,seata在进行undo日志处理时,JacksonUndoLogParser发生了反序列化报错。
具体错误信息如下
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `java.time.LocalDateTime` (no Creators, like default constructor, exist): cannot deserialize from Object value (no delegate- or property-based Creator)
at [Source: (String)"{"nano":356806000,"month":"APRIL","dayOfWeek":"MONDAY","dayOfYear":102,"year":2021,"monthValue":4,"dayOfMonth":12,"hour":9,"minute":31,"second":39,"chronology":{"calendarType":"iso8601","id":"ISO"}}"; line: 1, column: 2]
原因是: 数据库类型datetime在mysql8.0会被映射为LocalDateTime类型【具体映射可查看com.mysql.jdbc.ResultSetImpl.getObject()方法】,在序列化保存到数据库后使用jackson无法反序列化
查看JacksonUndoLogParser源码后发现仅增加Timestamp类的序列化和反序列化处理,对LocalDateTime的序列化和反序列化未做处理
private final ObjectMapper mapper = new ObjectMapper(); private final SimpleModule module = new SimpleModule(); public void init() { module.addSerializer(Timestamp.class, timestampSerializer); module.addDeserializer(Timestamp.class, timestampDeserializer); module.addSerializer(SerialBlob.class, blobSerializer); module.addDeserializer(SerialBlob.class, blobDeserializer); module.addSerializer(SerialClob.class, clobSerializer); module.addDeserializer(SerialClob.class, clobDeserializer); mapper.registerModule(module); mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY); mapper.enable(MapperFeature.PROPAGATE_TRANSIENT_MARKER); }
查看GitHub后发现已有人提出类似的问题,并且有人已经提交PR并合并到develop分支了,目前已经合并到1.4.2分支处理了。
项目中seata版本升级到1.4.2后,新建 JsonDateTimeSerializer 类
public class JsonDateTimeSerializer implements JacksonSerializer<LocalDateTime> { private static final DateTimeFormatter DATETIME_FORMAT = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); @Override public Class<LocalDateTime> type() { return LocalDateTime.class; } @Override public JsonSerializer<LocalDateTime> ser() { return new LocalDateTimeSerializer(DATETIME_FORMAT); } @Override public JsonDeserializer<? extends LocalDateTime> deser() { return new LocalDateTimeDeserializer(DATETIME_FORMAT); } }
然后在 resources 目录下新建 seata/io.seata.rm.datasource.undo.parser.spi.JacksonSerializer 文件
文件内填入 JsonDateTimeSerializer 类的完整路径。
com.xxx.seata.jackson.JsonDateTimeSerializer
至此就支持 LocalDateTime 的序列化和反序列化了。
参考文章:
https://blog.csdn.net/zh0134/article/details/115612416
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架