使用SpringData-MongoDB将Java 8 Instant存储为BSON日期

21
我有一个类想使用Spring Data存储到MongoDB中。
@Document()
public class Tuple2<T extends Enum<T>> {

@Id
private String id;

@Indexed
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
private final Instant timeCreated;

...
}

DateTimeFormat注解的Javadoc说明:

声明字段应格式化为日期和时间。支持通过样式模式、ISO日期时间模式或自定义格式模式字符串进行格式化。可应用于java.util.Date、java.util.Calendar、java.long.Long、Joda-Time值类型;自Spring 4和JDK 8以来,也适用于JSR-310 java.time类型。

我正在使用Spring 4.1.1和JDK 8,所以我期望它适用于Instant。然而,实际存储的内容如下:

"timeCreated" : {
    "seconds" : NumberLong(1416757496),
    "nanos" : 503000000
}

如果我按照这个答案的解释编写并注册了一个从Instant到Date的自定义转换器,它是有效的,但我想避免使用它,因为我相信一定有更好的方法。
在进一步深入研究Spring源代码后,我发现了以下看起来很有希望的类`Jsr310DateTimeFormatAnnotationFormatterFactory`:

使用JDK 8中的JSR-310 java.time包格式化使用DateTimeFormat注解注释的字段。

它的源代码没有参考`Instant`,但它确实参考了`OffsetTime`和`LocalTime`。即使这样,在我的示例中将`Instant`更改为`OffsetDateTime`之后,它仍然作为复合对象存储,而不是ISO日期。
缺少什么?
2个回答

4
我认为问题在于你试图将 Instant 用作时间,从概念上讲,它是时间轴上的一个点,不涉及格式化。
正如我们所知,Java 8 时间 API 是以 joda-time 为蓝本开发的(joda-time 的开发人员也参与其中)。这里是来自 joda-time 的 Instant 的评论:
“无论其他因素如何,例如年表或时区,都应该使用 Instant 来表示时间点。”
这就是为什么在 Spring 3.0 版本中出现了 JodaDateTimeFormatAnnotationFormatterFactory,但对于 org.joda.time.Instant 没有格式化可能性。并且在 Jsr310DateTimeFormatAnnotationFormatterFactory 中也没有实现。
因此,您应该使用自定义转换器或考虑使用更合适的类。

看起来还可以。然而,在Jsr310DateTimeFormatAnnotationFormatterFactory中有一个OffsetDateTime,但它没有被格式化好。 - Vic
@Vic,DateTimeFormat注解不负责在存储(mongodb)中进行格式化。它仅在应用程序级别工作(例如,在JSP页面上进行格式化)。有转换器可将数据转换为适当的类型。我只找到了Java 8时间API的“ZonedDateTimeToCalendarConverter”。因此,您可以尝试使用ZonedDateTime吗? - retroq

0

我在所有时间戳类型数据中使用instant,就像你的timecreated一样。如果是为了最终用户,比如日历条目,那么LocalDateTime更好,但它们都可以使用ISO格式化的时间字符串创建。在某个时候,时间数据(日期或即时)需要进行格式化以便于阅读或序列化/可移植性。

因此,回答这个问题,如果有人在当前MongoDB版本中遇到这个问题,你不需要在你的代码中做任何事情。我使用初始化脚本在我的mongodb容器中初始化了一些数据。我使用了ISODate格式。

 "timestamp": ISODate("2020-03-17T13:50:56.618Z")

我还有一个Spring Boot 2和Spring Data应用程序。文档对其提供了完全支持。 https://docs.spring.io/spring-data/mongodb/docs/current/reference/html/#mapping-conversion


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接