1. 概要

Spring Data MongoDB モジュールは、SpringプロジェクトでMongoDBデータベースと対話する際の読みやすさと使いやすさを向上させます。

このチュートリアルでは、MongoDBデータベースの読み取りおよび書き込み時に ZonedDateTimeJavaオブジェクトを処理する方法に焦点を当てます。

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 Date タイプの精度がミリ秒であるため、ナノ秒情報を削除しています。

@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 DataMongoDBにはZonedDateTimeコンバーターが定義されていません。それらを構成する方法を見てみましょう。

3. MongoDBコンバーター

ZonedDateTime オブジェクト(すべてのモデルにわたって)を処理するには、MongoDBから読み取るためのコンバーターと、それに書き込むためのコンバーターを定義します。

読むために、DateオブジェクトからZonedDateTimeオブジェクトに変換しています。 次の例では、 Date オブジェクトがゾーン情報を格納しないため、ZoneOffset.UTCを使用します。

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を使用します。 ZonedDateTimeReadConverterZonedDateTimeWriteConverterMongoCustomConversionsに追加されたので、テストに合格します。

保存されたオブジェクトの簡単な印刷は次のようになります。

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

MongoDBコンバーターの登録方法の詳細については、このチュートリアルを参照してください。

4. 結論

このクイック記事では、Java ZonedDateTimeオブジェクトを処理するためにMongoDBコンバーターを作成する方法を説明しました。

これらすべてのスニペットの実装は、GitHubにあります。