>

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

posted @   字节悦动  阅读(634)  评论(0编辑  收藏  举报
编辑推荐:
· 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 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架
点击右上角即可分享
微信分享提示