最新の安定バージョンについては、Spring Data MongoDB 5.0.2 を使用してください! |
MongoDB リポジトリ
この章では、MongoDB のリポジトリサポートの特殊性について説明します。この章は、コア概念で説明したコアリポジトリサポートに基づいて構築されています。そこで説明されている基本概念を十分に理解している必要があります。
使用方法
MongoDB に保存されているドメインエンティティにアクセスするには、実装を大幅に容易にする高度なリポジトリサポートを使用できます。これを行うには、次の例に示すように、リポジトリのインターフェースを作成します。
public class Person {
@Id
private String id;
private String firstname;
private String lastname;
private Address address;
// … getters and setters omitted
} 前の例に示されているドメイン型には、型 String の id という名前のプロパティがあることに注意してください。MongoTemplate (リポジトリサポートを支援する) で使用されるデフォルトの直列化メカニズムは、id という名前のプロパティをドキュメント ID とみなします。現在、ID 型として String、ObjectId、BigInteger をサポートしています。id フィールドがマッピング層でどのように処理されるかについての詳細は、ID マッピングを参照してください。
ドメインオブジェクトを取得したため、次のようにそれを使用するインターフェースを定義できます。
命令的
リアクティブ
public interface PersonRepository extends PagingAndSortingRepository<Person, String> {
// additional custom query methods go here
}
public interface PersonRepository extends ReactiveSortingRepository<Person, String> {
// additional custom query methods go here
}
リポジトリの使用を開始するには、@EnableMongoRepositories アノテーションを使用します。このアノテーションは、名前空間要素と同じ属性を持ちます。基本パッケージが構成されていない場合、インフラストラクチャーは、アノテーションが付けられた構成クラスのパッケージをスキャンします。次の例は、MongoDB リポジトリを使用するようにアプリケーションを構成する方法を示しています。
命令的
リアクティブ
XML
@Configuration
@EnableMongoRepositories("com.acme..repositories")
class ApplicationConfig extends AbstractMongoClientConfiguration {
@Override
protected String getDatabaseName() {
return "e-store";
}
@Override
protected String getMappingBasePackage() {
return "com.acme..repositories";
}
}
@Configuration
@EnableReactiveMongoRepositories("com.acme..repositories")
class ApplicationConfig extends AbstractReactiveMongoConfiguration {
@Override
protected String getDatabaseName() {
return "e-store";
}
@Override
protected String getMappingBasePackage() {
return "com.acme..repositories";
}
}
| MongoDB は、命令型 (同期 / ブロッキング) およびリアクティブ (ノンブロッキング) データアクセスに 2 つの異なるドライバーを使用します。Spring Data の Reactive MongoDB サポートに必要なインフラストラクチャを提供するには、Reactive Streams ドライバーを使用して接続を作成する必要があります。MongoDB の Reactive Streams ドライバー用に別の構成を提供する必要があります。リアクティブおよびブロッキング Spring Data MongoDB テンプレートおよびリポジトリを使用する場合、アプリケーションは 2 つの異なる接続で動作することに注意してください。 |
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mongo="http://www.springframework.org/schema/data/mongo"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/data/mongo
https://www.springframework.org/schema/data/mongo/spring-mongo-1.0.xsd">
<mongo:mongo-client id="mongoClient" />
<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
<constructor-arg ref="mongoClient" />
<constructor-arg value="databaseName" />
</bean>
<mongo:repositories base-package="com.acme.*.repositories" />
</beans>
この名前空間要素により、基本パッケージで MongoRepository を継承するインターフェースがスキャンされ、見つかったインターフェースごとに Spring Bean が作成されます。デフォルトでは、リポジトリは mongoTemplate と呼ばれる MongoTemplate Spring Bean を有線で取得するため、この規則から逸脱する場合のみ mongo-template-ref を明示的に構成する必要があります。
ドメインリポジトリは PagingAndSortingRepository を継承しているため、エンティティへのページ分割および並べ替えられたアクセスのためのメソッドが提供されます。リアクティブリポジトリの場合は、Page の概念が適用できないため、ReactiveSortingRepository のみが利用可能です。ただし、ファインダーメソッドは引き続き Sort および Limit パラメーターを受け入れます。
リアクティブスペースでは、さまざまなリアクティブ組成ライブラリを提供します。最も一般的なライブラリは RxJava [GitHub] (英語) およびプロジェクト Reactor (英語) です。 Spring Data MongoDB は MongoDB Reactive Streams (英語) ドライバー上に構築されており、Reactive Streams (英語) イニシアチブに依存することで最大限の相互運用性を提供します。 Spring Data のリアクティブリポジトリ抽象化は動的 API であり、クエリメソッドを宣言する際に、主にユーザーと要件によって定義されます。リアクティブ MongoDB リポジトリは、次のライブラリ固有のリポジトリインターフェースのいずれかを継承することにより、RxJava または Project Reactor ラッパー型を使用して実装できます。
Spring Data はバックグラウンドでリアクティブラッパー型を変換するため、お気に入りの合成ライブラリをそのまま使用できます。 |
基本的な CRUD 操作のメソッドを取得したい場合は、CrudRepository インターフェースも追加します。リポジトリインスタンスの操作は、依存関係をクライアントに注入するだけの問題です。ページサイズ 10 で Person オブジェクトの 2 番目のページにアクセスすると、次のコードのようになります。
命令的
リアクティブ
@ExtendWith(SpringExtension.class)
@ContextConfiguration
class PersonRepositoryTests {
@Autowired PersonRepository repository;
@Test
void readsFirstPageCorrectly() {
Page<Person> persons = repository.findAll(PageRequest.of(0, 10));
assertThat(persons.isFirstPage()).isTrue();
}
}
@ExtendWith(SpringExtension.class)
@ContextConfiguration
class PersonRepositoryTests {
@Autowired PersonRepository repository;
@Test
void readsFirstPageCorrectly() {
Flux<Person> persons = repository.findAll(Sort.unsorted(), Limit.of(10));
persons.as(StepVerifer::create)
.expectNextCount(10)
.verifyComplete();
}
}
前述の例では、Spring の単体テストサポートを使用してアプリケーションコンテキストを作成し、テストケースへのアノテーションベースの依存関係の注入を実行します。テストメソッド内では、リポジトリを使用してデータストアにクエリを実行します。ページサイズ 10 で Person オブジェクトの最初のページをリクエストする PageRequest インスタンスをリポジトリに渡します。
型安全なクエリメソッド
MongoDB リポジトリとそのリアクティブなリポジトリは、型 セーフなクエリを実行する方法を提供する Querydsl (英語) プロジェクトと統合されています。
クエリをインライン文字列として記述したり XML ファイルに外部化したりする代わりに、クエリは流れるような API を介して構築されます。
次の機能を提供します。
IDE の コード補完 (すべてのプロパティ、メソッド、操作は好みの Java IDE で拡張できます)。
構文的に無効なクエリはほとんど許可されません (すべてのレベルで型 セーフ)。
ドメインの型とプロパティは安全に参照できます。文字列は関係しません。
ドメイン型の変更のリファクタリングによりよく適応します。
増分クエリの定義が簡単になります。
Maven または Ant を使用して APT ベースのコード生成用に環境をブートストラップする方法については、QueryDSL ドキュメント (英語) を参照してください。
QueryDSL を使用すると、次のようなクエリを作成できます。
命令的
リアクティブ
QPerson person = new QPerson("person");
List<Person> result = repository.findAll(person.address.zipCode.eq("C0123"));
Page<Person> page = repository.findAll(person.lastname.contains("a"),
PageRequest.of(0, 2, Direction.ASC, "lastname"));
QPerson person = QPerson.person;
Flux<Person> result = repository.findAll(person.address.zipCode.eq("C0123"));
QPerson は、Java アノテーション後処理ツールによって生成されるクラスです。これは、型安全なクエリを作成できる Predicate です。クエリには C0123 値以外の文字列が含まれていないことに注意してください。
生成された Predicate クラスは、次のリストに示す QuerydslPredicateExecutor / ReactiveQuerydslPredicateExecutor インターフェースを使用して使用できます。
命令的
リアクティブ
public interface QuerydslPredicateExecutor<T> {
T findOne(Predicate predicate);
List<T> findAll(Predicate predicate);
List<T> findAll(Predicate predicate, Sort sort);
List<T> findAll(Predicate predicate, OrderSpecifier<?>... orders);
Page<T> findAll(Predicate predicate, Pageable pageable);
List<T> findAll(OrderSpecifier<?>... orders);
Long count(Predicate predicate);
Boolean exists(Predicate predicate);
}
interface ReactiveQuerydslPredicateExecutor<T> {
Mono<T> findOne(Predicate predicate);
Flux<T> findAll(Predicate predicate);
Flux<T> findAll(Predicate predicate, Sort sort);
Flux<T> findAll(Predicate predicate, OrderSpecifier<?>... orders);
Flux<T> findAll(OrderSpecifier<?>... orders);
Mono<Long> count(Predicate predicate);
Mono<Boolean> exists(Predicate predicate);
}
これをリポジトリ実装で使用するには、次の例に示すように、インターフェースの継承元となるリポジトリインターフェースのリストにこれを追加します。
命令的
リアクティブ
interface PersonRepository extends MongoRepository<Person, String>, QuerydslPredicateExecutor<Person> {
// additional query methods go here
}
interface PersonRepository extends ReactiveMongoRepository<Person, String>, ReactiveQuerydslPredicateExecutor<Person> {
// additional query methods go here
}
| 結合 (DBRef) は Reactive MongoDB サポートではサポートされていないことに注意してください。 |