Хранить Java 8 мгновенно в качестве даты BSON с помощью SpringData-MongoDB

У меня есть следующий класс, который я хочу сохранить в MongoDB, используя Spring Data​​p >

@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, для типов java.time JSR-310.

Я использую Spring 4.1.1 и JDK 8, поэтому я ожидаю, что это применимо к Instant. Однако вот что на самом деле хранится:

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

Если я пишу и регистрирую пользовательский преобразователь от Instant to Date, как описано в этом ответе, то он работает, однако я бы хотел этого избежать, поскольку я уверен должен быть лучший способ.

После дальнейшего копания в исходном коде Spring я нашел следующий класс Jsr310DateTimeFormatAnnotationFormatterFactory, который выглядит многообещающим:

Форматирует поля, аннотированные аннотацией DateTimeFormat с использованием пакета java.time JSR-310 в JDK 8.

Его источник не ссылается на Instant, но он ссылается на OffsetTime и LocalTime. Тем не менее, когда я изменяю Instant в качестве OffsetDateTime в моем примере, он по-прежнему сохраняется как составной объект вместо ISODate.

Что не хватает?

Ответы

Ответ 1

Я думаю, что проблема заключается в том, что вы пытаетесь использовать Instant как время. Концептуально это точка временной шкалы, и это не означает форматирование.

Как мы знаем, Java 8 time API был разработан с глазу на joda-time (и с участием разработчиков joda-времени). Вот комментарий от joda-time Instant:

Мгновенное действие должно использоваться для представления точки во времени независимо от любого другого фактора, например хронологии или часового пояса.

Поэтому нет возможности форматирования для org.joda.time.Instant в JodaDateTimeFormatAnnotationFormatterFactory, которая появилась в Spring с версии 3.0. А также он не был реализован в Jsr310DateTimeFormatAnnotationFormatterFactory

Итак, вы должны использовать пользовательский конвертер или считаете, что используете более подходящий класс.