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

问题描述 投票:17回答:2

我有以下要使用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
}

如果我像this answer中所述编写并注册从Instant到Date的自定义转换器,则它可以工作,但是我想避免这种情况,因为我确信必须有更好的方法。

在进一步挖掘Spring源代码之后,我发现了以下类Jsr310DateTimeFormatAnnotationFormatterFactory,看起来很有希望:

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

其来源未引用Instant,但确实引用了OffsetTime和LocalTime。即使这样,在我的示例中将Instant更改为OffsetDateTime时,它仍存储为复合对象而不是ISODate。

缺少什么?

java spring spring-data spring-data-mongodb java-time
2个回答
4
投票

我认为问题是您尝试使用Instant作为时间。从概念上讲,它是时间轴上的一个点,并不意味着要进行格式化。

[我们知道,Java 8 time API是在joda-time(以及joda-time的开发人员的参与)的眼中开发的。这是joda-time Instant的评论:

Instant应该用来表示时间点不受其他因素影响,例如时间顺序或时区。

这就是为什么自3.0版开始出现在org.joda.time.Instant中的JodaDateTimeFormatAnnotationFormatterFactory中没有格式化可能性的原因。而且也没有在Jsr310DateTimeFormatAnnotationFormatterFactory

中实现

因此,您应该使用自定义转换器或考虑使用更合适的类。


0
投票

我将即时用于所有时间戳类型的数据,就像您创建的时间一样。如果它是针对最终用户的(例如日历项),则它比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

© www.soinside.com 2019 - 2024. All rights reserved.