我的问题就像这样CodecConfigurationException when saving ZonedDateTime to MongoDB with Spring Boot >= 2.0.1.RELEASE
但是我写了一个自定义的ZonedDateTime转换器:
ZonedDateTimeToDateConverter
@WritingConverter
public class ZonedDateTimeToDateConverter implements Converter<ZonedDateTime, Date> {
@Override
public Date convert(ZonedDateTime source) {
if (source == null) {
return null;
}
return Date.from(source.toInstant());
}
}
DateToZonedDateTimeConverter
@ReadingConverter
public class DateToZonedDateTimeConverter implements Converter<Date, ZonedDateTime> {
@Override
public ZonedDateTime convert(Date source) {
if (source == null) {
return null;
}
return ZonedDateTime.ofInstant(source.toInstant(), ZoneId.of("UTC"));
}
}
我的测试:
@Autowired
ReactiveMongoOperations operations;
@Test
void test() {
ObjectId id = new ObjectId();
Document doc = new Document();
doc.append("_id", id);
// doc.append("a", ZonedDateTime.now()); // works
doc.append("zd1", new Document("f", ZonedDateTime.now())); // not working
operations.insert(doc, "test-collection").block();
Document found = Mono.from(operations.getCollection("test-collection")
.find(new Document("_id", id)).first()).block();
Assertions.assertNotNull(found);
}
如果我将一个ZDT示例添加到文档第一级,如doc.append("a", ZonedDateTime.now())
-document保存良好。但是,如果我将一个ZDT示例作为嵌套字段(嵌套的第二层)放置到文档中,我会收到一个异常:
org. bson. codecs. configuration. CodecConfigurationException:找不到java.time.ZonedDateTime类的编解码器。
我做错了什么?
2条答案
按热度按时间zi8p0yeb1#
我通过将转换器添加到自定义转换器配置来解决类似的问题:
5m1hhzi42#
我完全避免使用Date或ZonedDateTime,而是使用了一个自定义类型,它 Package 了LocalDateTime,并使用它转换为DB的字符串。这可以防止MongoDB转换为UTC,同时将LocalDateTime的自定义类型留在业务级别进行转换和比较。您需要有一个单独的时区属性。这样,当比较或移动到另一个本地时间时,您可以在演示级别或类似级别创建一个新的ZonedDateTime。为了做到这一点,我使用了Chamindu在his site中描述的技术。只要确保扩展AbstractMongoClientConfiguration而不是AbstractMongoConfiguration。如果使用带有datetime-local的HTML5表单(即带有thymeleaf:
<input type="datetime-local" th:field="*{myDate}"/>
),您需要更改Chamindu指示的字符串格式,以便DB匹配输入所需的内容。在HTML表单和Mongo DB中对我都有效的字符串格式是。“yyyy-MM-dd'T'HH:mm:ss”而不是“yyyy-MM-dd'T'HHss.SSS”。注意:我不确定自定义类型如何影响验证和其他功能。