リポジトリインターフェースの定義
リポジトリインターフェースを定義するには、最初にドメインクラス固有のリポジトリインターフェースを定義する必要があります。インターフェースは Repository
を継承し、ドメインクラスと ID 型に入力する必要があります。そのドメイン型の CRUD メソッドを公開する場合は、CrudRepository
、または Repository
の代わりにそのバリアントの 1 つを継承できます。
リポジトリ定義の微調整
リポジトリインターフェースを使い始める方法にはいくつかのバリエーションがあります。
典型的なアプローチは、CrudRepository
を継承することです。これにより、CRUD 機能のメソッドが提供されます。CRUD は、Create、Read、Update、Delete の略です。バージョン 3.0 では、CrudRepository
と非常によく似た ListCrudRepository
も導入されましたが、複数のエンティティを返すメソッドでは、使いやすい Iterable
ではなく List
が返されます。
リアクティブストアを使用している場合は、使用しているリアクティブフレームワークに応じて ReactiveCrudRepository
または RxJava3CrudRepository
を選択できます。
Kotlin を使用している場合は、Kotlin のコルーチンを利用する CoroutineCrudRepository
を選択できます。
さらに、Sort
抽象化または前者の場合は Pageable
抽象化を指定できるメソッドが必要な場合は、PagingAndSortingRepository
、ReactiveSortingRepository
、RxJava3SortingRepository
または CoroutineSortingRepository
を継承できます。さまざまなソートリポジトリは、3.0 より前の Spring Data バージョンのように、それぞれの CRUD リポジトリを継承しなくなったことに注意してください。両方の機能が必要な場合は、両方のインターフェースを継承する必要があります。
Spring Data インターフェースを継承したくない場合は、リポジトリインターフェースに @RepositoryDefinition
でアノテーションを付けることもできます。CRUD リポジトリインターフェースの 1 つを継承すると、エンティティを操作するためのメソッドの完全なセットが公開されます。公開するメソッドを選択したい場合は、公開するメソッドを CRUD リポジトリからドメインリポジトリにコピーします。その際、メソッドの戻り値の型を変更できます。Spring Data は、可能であれば戻り値の型を尊重します。例: 複数のエンティティを返すメソッドの場合、Iterable<T>
、List<T>
、Collection<T>
または VAVR リストを選択できます。
アプリケーション内の多くのリポジトリに同じメソッドのセットが必要な場合は、継承元の独自のベースインターフェースを定義できます。このようなインターフェースには、@NoRepositoryBean
のアノテーションを付ける必要があります。これにより、Spring Data はインスタンスを直接作成しようとして失敗し、そのリポジトリのエンティティを特定できないために失敗します。これは、ジェネリクス型変数がまだ含まれているためです。
次の例は、CRUD メソッド(この場合は findById
および save
)を選択的に公開する方法を示しています。
@NoRepositoryBean
interface MyBaseRepository<T, ID> extends Repository<T, ID> {
Optional<T> findById(ID id);
<S extends T> S save(S entity);
}
interface UserRepository extends MyBaseRepository<User, Long> {
User findByEmailAddress(EmailAddress emailAddress);
}
前の例では、すべてのドメインリポジトリと公開された findById(…)
および save(…)
に共通のベースインターフェースを定義しました。これらのメソッドは、Spring Data が提供する選択のストアのベースリポジトリ実装にルーティングされます(たとえば、JPA を使用する場合、実装は SimpleJpaRepository
です)。これは、それらが CrudRepository
のメソッドシグネチャーと一致するためです。そのため、UserRepository
はユーザーを保存し、ID で個々のユーザーを検索し、メールアドレスで Users
を検索するクエリをトリガーできるようになりました。
中間リポジトリインターフェースには @NoRepositoryBean のアノテーションが付けられています。Spring Data が実行時にインスタンスを作成してはならないすべてのリポジトリインターフェースに、そのアノテーションを必ず追加してください。 |
複数の Spring Data モジュールでリポジトリを使用する
定義済みスコープ内のすべてのリポジトリインターフェースが Spring Data モジュールにバインドされているため、アプリケーションで一意の Spring Data モジュールを使用すると、物事が簡単になります。アプリケーションによっては、複数の Spring Data モジュールを使用する必要がある場合があります。そのような場合、リポジトリ定義は永続化テクノロジーを区別する必要があります。クラスパスで複数のリポジトリファクトリを検出すると、Spring Data は厳密なリポジトリ構成モードに入ります。厳密な構成では、リポジトリまたはドメインクラスの詳細を使用して、リポジトリ定義の Spring Data モジュールバインディングについて決定します。
リポジトリ定義がモジュール固有のリポジトリを継承する場合、特定の Spring Data モジュールの有効な候補です。
ドメインクラスにモジュール固有の型アノテーションが付けられている場合、そのクラスは特定の Spring Data モジュールの有効な候補となります。Spring Data モジュールは、サードパーティのアノテーション (JPA の
@Entity
など) を受け入れるか、独自のアノテーション (Spring Data MongoDB および Spring Data Elasticsearch の@Document
など) を提供します。
次の例は、モジュール固有のインターフェース(この場合は JPA)を使用するリポジトリを示しています。
interface MyRepository extends JpaRepository<User, Long> { }
@NoRepositoryBean
interface MyBaseRepository<T, ID> extends JpaRepository<T, ID> { … }
interface UserRepository extends MyBaseRepository<User, Long> { … }
MyRepository
および UserRepository
は、型階層で JpaRepository
を継承します。それらは、Spring Data JPA モジュールの有効な候補です。
次の例は、汎用インターフェースを使用するリポジトリを示しています。
interface AmbiguousRepository extends Repository<User, Long> { … }
@NoRepositoryBean
interface MyBaseRepository<T, ID> extends CrudRepository<T, ID> { … }
interface AmbiguousUserRepository extends MyBaseRepository<User, Long> { … }
AmbiguousRepository
と AmbiguousUserRepository
は、型階層内の Repository
と CrudRepository
のみを継承します。一意の Spring Data モジュールを使用する場合はこれで問題ありませんが、複数のモジュールでは、これらのリポジトリをどの特定の Spring Data にバインドする必要があるかを区別できません。
次の例は、アノテーション付きのドメインクラスを使用するリポジトリを示しています。
interface PersonRepository extends Repository<Person, Long> { … }
@Entity
class Person { … }
interface UserRepository extends Repository<User, Long> { … }
@Document
class User { … }
PersonRepository
は、JPA @Entity
アノテーションが付けられた Person
を参照しているため、このリポジトリは明らかに Spring Data JPA に属しています。UserRepository
は、Spring Data MongoDB の @Document
アノテーションでアノテーションが付けられた User
を参照します。
次の悪い例は、アノテーションが混在するドメインクラスを使用するリポジトリを示しています。
interface JpaPersonRepository extends Repository<Person, Long> { … }
interface MongoDBPersonRepository extends Repository<Person, Long> { … }
@Entity
@Document
class Person { … }
この例は、JPA アノテーションと Spring Data MongoDB アノテーションの両方を使用するドメインクラスを示しています。JpaPersonRepository
と MongoDBPersonRepository
の 2 つのリポジトリを定義します。1 つは JPA 用で、もう 1 つは MongoDB での使用を目的としています。Spring Data はリポジトリを区別できなくなり、未定義の動作につながります。
リポジトリ型の詳細および識別ドメインクラスアノテーションは、特定の Spring Data モジュールのリポジトリ候補を識別するための厳密なリポジトリ構成に使用されます。同じドメイン型で複数の永続化テクノロジ固有のアノテーションを使用することが可能であり、複数の永続化テクノロジでドメイン型を再利用できます。ただし、Spring Data は、リポジトリをバインドする一意のモジュールを決定できなくなります。
リポジトリを区別する最後の方法は、リポジトリの基本パッケージのスコープを設定することです。基本パッケージは、リポジトリインターフェース定義をスキャンするための開始点を定義します。これは、リポジトリ定義が適切なパッケージに配置されることを意味します。デフォルトでは、アノテーション駆動型構成は構成クラスのパッケージを使用します。XML ベースの構成の基本パッケージは必須です。
次の例は、基本パッケージのアノテーション駆動型の構成を示しています。
@EnableJpaRepositories(basePackages = "com.acme.repositories.jpa")
@EnableMongoRepositories(basePackages = "com.acme.repositories.mongo")
class Configuration { … }