コアコンセプト

Spring Data リポジトリ抽象化の中心的なインターフェースは Repository です。これは、管理するドメインクラスと、ドメインクラスの識別子型を型引数として受け取ります。このインターフェースは主に、操作する型をキャプチャーし、このインターフェースを継承するインターフェースを見つけるのに役立つマーカーインターフェースとして機能します。

Spring Data では、ドメイン型をエンティティ、より具体的には集約と見なします。そのため、ドキュメント全体で「エンティティ」という用語が使用されていますが、これは「ドメイン型」または「集約」という用語と置き換えることができます。

すでにお気づきかもしれませんが、導入部でドメイン駆動の概念について触れています。DDD の意味でドメインオブジェクトを検討します。ドメインオブジェクトには識別子があり (そうでない場合は、これらは ID のない値オブジェクトになります)、データにアクセスするために特定のパターンを操作するときに、何らかのメソッドで識別子を参照する必要があります。リポジトリとクエリメソッドについて説明すると、識別子の参照がより意味を持ちます。

CrudRepository (Javadoc) および ListCrudRepository (Javadoc) インターフェースは、管理対象のエンティティクラスに高度な CRUD 機能を提供します。

CrudRepository インターフェース
public interface CrudRepository<T, ID> extends Repository<T, ID> {

  <S extends T> S save(S entity);      (1)

  Optional<T> findById(ID primaryKey); (2)

  Iterable<T> findAll();               (3)

  long count();                        (4)

  void delete(T entity);               (5)

  boolean existsById(ID primaryKey);   (6)

  // … more functionality omitted.
}
1 指定されたエンティティを保存します。
2 指定された ID で識別されるエンティティを返します。
3 すべてのエンティティを返します。
4 エンティティの数を返します。
5 指定されたエンティティを削除します。
6 指定された ID のエンティティが存在するかどうかを示します。

このインターフェースで宣言されたメソッドは、一般に CRUD メソッドと呼ばれます。ListCrudRepository は同等のメソッドを提供しますが、CrudRepository メソッドが Iterable を返すのに対し、それらは List を返します。

リポジトリインターフェースには、プロパティ名に関係なくドメイン型識別子プロパティをターゲットとする findById(ID identifier) などの予約済みメソッドがいくつか含まれています。詳細については、"クエリメソッドの定義" を参照してください。

Id という名前のプロパティが識別子を参照しない場合は、クエリメソッドに @Query のアノテーションを付けてカスタムクエリを提供できます。このパスに従うと混乱が生じやすく、ID 型と Id プロパティの型が異なる場合はすぐに型の制限に達するため、推奨されません。

また、JpaRepository や MongoRepository などの永続化技術固有の抽象化も提供します。これらのインターフェースは CrudRepository を継承し、CrudRepository などのかなり汎用的な永続化テクノロジーにとらわれないインターフェースに加えて、基礎となる永続化テクノロジーの機能を公開します。

CrudRepository に加えて、エンティティへのページ分割されたアクセスを容易にする追加のメソッドを追加する PagingAndSortingRepository (Javadoc) および ListPagingAndSortingRepository (Javadoc) があります。

PagingAndSortingRepository インターフェース
public interface PagingAndSortingRepository<T, ID>  {

  Iterable<T> findAll(Sort sort);

  Page<T> findAll(Pageable pageable);
}
拡張インターフェースは、実際のストアモジュールによってサポートされる必要があります。このドキュメントでは一般的なスキームについて説明していますが、ストアモジュールが使用したいインターフェースをサポートしていることを確認してください。

20 のページサイズで User の 2 番目のページにアクセスするには、次のようなことができます。

PagingAndSortingRepository<User, Long> repository = // … get access to a bean
Page<User> users = repository.findAll(PageRequest.of(1, 20));

ListPagingAndSortingRepository は同等のメソッドを提供しますが、PagingAndSortingRepository メソッドが Iterable を返すのに対し、List を返します。

クエリメソッドに加えて、カウントクエリと削除クエリの両方のクエリ派生を使用できます。次のリストは、派生カウントクエリのインターフェース定義を示しています。

派生カウントクエリ
interface UserRepository extends CrudRepository<User, Long> {

  long countByLastname(String lastname);
}

次のリストは、派生削除クエリのインターフェース定義を示しています。

派生削除クエリ
interface UserRepository extends CrudRepository<User, Long> {

  long deleteByLastname(String lastname);

  List<User> removeByLastname(String lastname);
}

エンティティ状態検出戦略

次の表は、エンティティが新しいかどうかを検出するために Spring Data が提供する戦略を説明しています。

表 1: Spring Data でエンティティが新しいかどうかを検出するためのオプション

@Id-Property inspection (the default)

By default, Spring Data inspects the identifier property of the given entity. If the identifier property is null or 0 in case of primitive types, then the entity is assumed to be new. Otherwise, it is assumed to not be new.

@Version-Property inspection

If a property annotated with @Version is present and null, or in case of a version property of primitive type 0 the entity is considered new. If the version property is present but has a different value, the entity is considered to not be new. If no version property is present Spring Data falls back to inspection of the identifier property.

Implementing Persistable

エンティティが Persistable を実装している場合、Spring Data はエンティティの isNew(…) メソッドに新しい検出を委譲します。詳細については、Javadoc を参照してください。

注: AccessType.PROPERTY を使用すると、Persistable のプロパティが検出されて保持されます。これを回避するには、@Transient を使用します

カスタム EntityInformation 実装の提供

モジュール固有のリポジトリファクトリのサブクラスを作成し、getEntityInformation(…) メソッドをオーバーライドすることにより、リポジトリベースの実装で使用される EntityInformation 抽象化をカスタマイズできます。次に、モジュール固有のリポジトリファクトリのカスタム実装を Spring Bean として登録する必要があります。これが必要になることはめったにないことに注意してください。