版本
io.seata:seata-spring-boot-starter:1.3.0
现象
数据实体对象字段类型为LocalDateTime时启用全局事务报错
json encode exception, Type id handling not implemented for type java.lang.Object (by serializer of type com.fasterxml.jackson.databind.ser.impl.UnsupportedTypeSerializer)
解决
- 升级依赖io.seata:seata-spring-boot-starter:1.4.2
- 自定义序列化器
public class LocalDateTimeJacksonSerializer implements JacksonSerializer {
private final static String DATETIME_PATTERN = "yyyy-MM-dd'T'HH:mm:ss.SSSSSSSSS";
private final static DateTimeFormatter DATETIME_FORMAT = DateTimeFormatter.ofPattern(DATETIME_PATTERN);
@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);
}
}
- 添加SPI扩展配置
META-INF/seata/io.seata.rm.datasource.undo.parser.spi.JacksonSerializer
LocalDateTimeJacksonSerializer
源码
- 回滚解析器
io.seata.rm.datasource.undo.parser.JacksonUndoLogParser
- io.seata:seata-spring-boot-starter:1.3.0中回滚日志解析器时间类型只对Timestamp类型处理
@Override
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);
}
- io.seata:seata-spring-boot-starter:1.4.2中增加了扩展点
@Override
public void init() {
try {
List<JacksonSerializer> jacksonSerializers = EnhancedServiceLoader.loadAll(JacksonSerializer.class);
if (CollectionUtils.isNotEmpty(jacksonSerializers)) {
for (JacksonSerializer jacksonSerializer : jacksonSerializers) {
Class type = jacksonSerializer.type();
JsonSerializer ser = jacksonSerializer.ser();
JsonDeserializer deser = jacksonSerializer.deser();
if (type != null) {
if (ser != null) {
module.addSerializer(type, ser);
}
if (deser != null) {
module.addDeserializer(type, deser);
}
LOGGER.info("jackson undo log parser load [{}].", jacksonSerializer.getClass().getName());
}
}
}
} catch (EnhancedServiceNotFoundException e) {
LOGGER.warn("JacksonSerializer not found children class.", e);
}
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);
}