テンプレート API

MongoTemplate (Javadoc) と、org.springframework.data.mongodb.core パッケージにあるそのリアクティブ (Javadoc) 対応クラスは、Spring の MongoDB サポートの中心となるクラスであり、データベースと対話するための豊富な機能セットを提供します。このテンプレートは、MongoDB ドキュメントの作成、更新、削除、クエリを行うための便利な操作を提供し、ドメインオブジェクトと MongoDB ドキュメント間のマッピングを提供します。

一度構成すると、MongoTemplate はスレッドセーフになり、複数のインスタンスで再利用できます。

便利なメソッド

MongoTemplate (Javadoc) クラスは、インターフェース MongoOperations (Javadoc) を実装します。可能な限り、MongoOperations のメソッドは、MongoDB ドライバー Collection オブジェクトで使用可能なメソッドにちなんで命名され、ドライバー API に慣れている既存の MongoDB 開発者に API が馴染みやすいものになっています。たとえば、findfindAndModifyfindAndReplacefindOneinsertremovesaveupdateupdateMulti などのメソッドがあります。設計ゴールは、ベース MongoDB ドライバーと MongoOperations の使用間の移行を可能な限り容易にすることでした。2 つの API の主な違いは、MongoOperations には Document ではなくドメインオブジェクトを渡すことができることです。また、MongoOperations には、Document を設定してそれらの操作のパラメーターを指定する代わりに、QueryCriteriaUpdate 操作用の流れるような API があります。

詳細については、ドキュメントの CRUD およびクエリセクションを参照してください。

MongoTemplate インスタンスの操作を参照するための推奨される方法は、そのインターフェース MongoOperations を使用することです。

コールバックの実行

MongoTemplate は、一般的なタスクを簡単に実行できるようにするための便利なメソッドを多数提供します。ただし、MongoDB ドライバー API に直接アクセスする必要がある場合は、いくつかの Execute コールバックメソッドのいずれかを使用できます。execute コールバックは、MongoCollection オブジェクトまたは MongoDatabase オブジェクトへの参照を提供します。

  • <T> T execute (Class<?> entityClass, CollectionCallback<T> action): 指定されたクラスのエンティティコレクションに対して指定された CollectionCallback を実行します。

  • <T> T execute (String collectionName, CollectionCallback<T> action): 指定された名前のコレクションに対して指定された CollectionCallback を実行します。

  • <T> T execute (DbCallback<T> action): DbCallback を実行し、必要に応じて例外を変換します。Spring Data MongoDB は、バージョン 2.2 で MongoDB に導入された集約 フレームワークのサポートを提供します。

  • <T> T execute (String collectionName, DbCallback<T> action): 指定された名前のコレクションに対して DbCallback を実行し、必要に応じて例外を変換します。

  • <T> T executeInSession (DbCallback<T> action): 書き込んだデータを読み取る可能性がある書き込み負荷の高い環境で一貫性を確保するために、データベースへの同じ接続内で指定された DbCallback を実行します。

次の例では、CollectionCallback (Javadoc) を使用してインデックスに関する情報を返します。

  • 命令的

  • リアクティブ

boolean hasIndex = template.execute("geolocation", collection ->
    Streamable.of(collection.listIndexes(org.bson.Document.class))
        .stream()
        .map(document -> document.get("name"))
        .anyMatch("location_2d"::equals)
);
Mono<Boolean> hasIndex = template.execute("geolocation", collection ->
    Flux.from(collection.listIndexes(org.bson.Document.class))
        .map(document -> document.get("name"))
        .filterWhen(name -> Mono.just("location_2d".equals(name)))
        .map(it -> Boolean.TRUE)
        .single(Boolean.FALSE)
    ).next();

Fluent API

MongoDB とのより低レベルの対話に関して中心的なコンポーネントである MongoTemplate は、コレクション作成、インデックス作成、CRUD 操作から、Map-Reduce や集計などのより高度な機能までのニーズをカバーする幅広いメソッドを提供します。メソッドごとに複数のオーバーロードが見つかります。それらのほとんどは、API のオプションまたは null 許容部分をカバーしています。

FluentMongoOperations は、MongoOperations の一般的なメソッドに対してより狭いインターフェースを提供し、より読みやすく流れるような API を提供します。エントリポイント (insert(…)find(…)update(…) など) は、実行される操作に基づいた自然な命名スキーマに従います。エントリポイントから先に進むと、API は、実際の MongoOperations 版 (次の例の場合は all メソッド) を呼び出す終了メソッドにつながる、コンテキスト依存のメソッドのみを提供するように設計されています。

命令的
List<Jedi> all = template.query(SWCharacter.class) (1)
  .inCollection("star-wars") (2)
  .as(Jedi.class) (3)
  .matching(query(where("jedi").is(true))) (4)
  .all();
1 クエリで使用されるフィールドのマッピングに使用される型。
2 ドメイン型で定義されていない場合に使用するコレクション名。
3 元のドメイン型を使用していない場合の結果の型。
4 ルックアップクエリ。
リアクティブ
Flux<Jedi> all = template.query(SWCharacter.class)
  .inCollection("star-wars")
  .as(Jedi.class)
  .matching(query(where("jedi").is(true)))
  .all();
射影を使用すると、MongoTemplate は実際のレスポンスを射影ターゲット型に必要なフィールドに制限することで、結果のマッピングを最適化できます。これは、Query (Javadoc) 自体にフィールド制限が含まれず、ターゲット型がクローズドインターフェースまたは DTO 射影である限り適用されます。
DBRef に射影を適用してはなりません。

単一エンティティの取得と、終了メソッド first()one()all() または stream() を使用した List または Stream としての複数のエンティティの取得を切り替えることができます。

near(NearQuery) を使用して地理空間クエリを作成する場合、次の例に示すように、終了メソッドの数は、MongoDB で geoNear コマンドを実行する ( GeoResults 内の GeoResult としてエンティティをフェッチする) ために有効なメソッドのみを含むように変更されます。

  • 命令的

  • リアクティブ

GeoResults<Jedi> results = template.query(SWCharacter.class)
  .as(Jedi.class)
  .near(alderaan) // NearQuery.near(-73.9667, 40.78).maxDis…
  .all();
Flux<GeoResult<Jedi>> results = template.query(SWCharacter.class)
  .as(Jedi.class)
  .near(alderaan) // NearQuery.near(-73.9667, 40.78).maxDis…
  .all();

例外変換

Spring フレームワークは、さまざまなデータベースおよびマッピングテクノロジの例外変換を提供します。これは従来、JDBC および JPA を対象としていました。MongoDB の Spring サポートは、org.springframework.dao.support.PersistenceExceptionTranslator インターフェースの実装を提供することで、この機能を MongoDB データベースに拡張します。

Spring の一貫したデータアクセス例外階層へのマッピングの背景となる動機は、MongoDB エラーコードに対するコーディングに頼ることなく、移植可能で記述的な例外処理コードを作成できることです。Spring のデータアクセス例外はすべてルート DataAccessException クラスから継承されるため、単一の try-catch ブロック内ですべてのデータベース関連の例外を確実にキャッチできます。MongoDB ドライバーによってスローされるすべての例外が MongoException クラスから継承されるわけではないことに注意してください。内部例外とメッセージは情報が失われないように保存されます。

MongoExceptionTranslator (Javadoc) によって実行されるマッピングには、com.mongodb.Network から DataAccessResourceFailureException および MongoException エラーコード 1003, 12001, 12010, 12011,, 12012 から InvalidDataAccessApiUsageException などがあります。マッピングの詳細については、実装を参照してください。

例外変換は、MongoDatabaseFactory またはそのリアクティブバリアントにカスタマイズされた MongoExceptionTranslator (Javadoc) を設定することで構成できます。対応する MongoClientFactoryBean に例外トランスレータを設定することもできます。

例 1: MongoExceptionTranslator の構成
ConnectionString uri = new ConnectionString("mongodb://username:password@localhost/database");
SimpleMongoClientDatabaseFactory mongoDbFactory = new SimpleMongoClientDatabaseFactory(uri);
mongoDbFactory.setExceptionTranslator(myCustomExceptionTranslator);

例外をカスタマイズする動機としては、トランザクション中の MongoDB の動作が挙げられます。この動作では、一部の障害 (書き込み競合など) が一時的なものになり、再試行によって操作が成功する場合もあります。このような場合、例外を特定の MongoDB ラベルでラップし、異なる例外変換戦略を適用できます。

ドメイン型のマッピング

MongoDB ドキュメントとドメインクラス間のマッピングは、MongoConverter (Javadoc) インターフェースの実装に委譲することによって行われます。Spring は MappingMongoConverter (Javadoc) を提供しますが、独自のコンバーターを作成することもできます。MappingMongoConverter は追加のメタデータを使用してオブジェクトとドキュメントのマッピングを指定できますが、ID とコレクション名のマッピングに関するいくつかの規則を使用して、追加のメタデータを含まないオブジェクトを変換することもできます。これらの規則とマッピングアノテーションの使用については、マッピングの章で説明されています。