<导航

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 @ 2022-04-16 15:37  奕锋博客  阅读(79)  评论(0编辑  收藏  举报