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

我希望使用Spring数据将以下类存储在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值类型;从Spring4和JDK 8开始,也可应用于JSR-310的java.time类型。

我使用的是Spring4.1.1和JDK8,所以我希望它适用于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。

缺少什么?


解决方案

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

正如我们所知,Java 8 Time API的开发着眼于joda-time(并关注joda-time的开发人员)。以下是来自joda-timeInstant的评论:

应使用Instant来表示时间点 不考虑任何其他因素,如年表或时区。

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

中也没有实现

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

相关文章