Перейти к основному содержимому

ZonedDateTime с Spring Data MongoDB

· 3 мин. чтения

1. Обзор

Модуль Spring Data MongoDB улучшает читаемость и удобство использования при взаимодействии с базой данных MongoDB в проектах Spring.

В этом руководстве мы сосредоточимся на том, как обрабатывать объекты Java ZonedDateTime при чтении и записи в базу данных MongoDB.

2. Настройка

Для работы с модулем Spring Data MongoDB нам нужно добавить следующую зависимость:

<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
<version>3.0.3.RELEASE</version>
</dependency>

Последнюю версию библиотеки можно найти здесь .

Давайте определим класс модели под названием Action (с атрибутом ZonedDateTime ):

@Document
public class Action {
@Id
private String id;

private String description;
private ZonedDateTime time;

// constructor, getters and setters
}

Для взаимодействия с MongoDB мы также создадим интерфейс, расширяющий MongoRepository :

public interface ActionRepository extends MongoRepository<Action, String> { }

Теперь мы определим тест, который вставит объект Action в MongoDB и подтвердит, что он был сохранен с правильным временем. В оценке утверждения мы удаляем информацию о наносекундах, поскольку тип даты MongoDB имеет точность в миллисекундах:

@Test
public void givenSavedAction_TimeIsRetrievedCorrectly() {
String id = "testId";
ZonedDateTime now = ZonedDateTime.now(ZoneOffset.UTC);

actionRepository.save(new Action(id, "click-action", now));
Action savedAction = actionRepository.findById(id).get();

Assert.assertEquals(now.withNano(0), savedAction.getTime().withNano(0));
}

Из коробки мы получим следующую ошибку при запуске нашего теста:

org.bson.codecs.configuration.CodecConfigurationException:
Can't find a codec for class java.time.ZonedDateTime

Spring Data MongoDB не имеет определенных преобразователей ZonedDateTime . Давайте посмотрим, как мы можем их настроить.

3. Преобразователи MongoDB

Мы можем обрабатывать объекты ZonedDateTime (во всех моделях), определяя преобразователь для чтения из MongoDB и один для записи в нее.

Для чтения мы конвертируем объект Date в объект ZonedDateTime . В следующем примере мы используем ZoneOffset.UTC, поскольку объект Date не хранит информацию о зоне:

public class ZonedDateTimeReadConverter implements Converter<Date, ZonedDateTime> {
@Override
public ZonedDateTime convert(Date date) {
return date.toInstant().atZone(ZoneOffset.UTC);
}
}

Затем мы преобразуем объект ZonedDateTime в объект Date . При необходимости мы можем добавить информацию о зоне в другое поле:

public class ZonedDateTimeWriteConverter implements Converter<ZonedDateTime, Date> {
@Override
public Date convert(ZonedDateTime zonedDateTime) {
return Date.from(zonedDateTime.toInstant());
}
}

Поскольку объекты Date не хранят смещение зоны, в наших примерах мы используем UTC . Теперь, когда ZonedDateTimeReadConverter и ZonedDateTimeWriteConverter добавлены в MongoCustomConversions , наш тест будет пройден.

Простая печать сохраненного объекта будет выглядеть так:

Action{id='testId', description='click', time=2018-11-08T08:03:11.257Z}

Чтобы узнать больше о том, как зарегистрировать преобразователи MongoDB, мы можем обратиться к этому руководству .

4. Выводы

В этой быстрой статье мы увидели, как создавать преобразователи MongoDB для обработки объектов Java ZonedDateTime .

Реализацию всех этих фрагментов можно найти на GitHub .