定義 Repository 介面

要定義儲存庫介面,首先需要定義一個特定於領域類的儲存庫介面。該介面必須擴充套件 Repository,並指定領域類和 ID 型別。如果您想為該領域型別公開 CRUD 方法,您可以擴充套件 CrudRepository 或其變體之一,而不是 Repository

微調儲存庫定義

有幾種方法可以開始使用您的儲存庫介面。

典型的方法是擴充套件 CrudRepository,它提供了 CRUD 功能的方法。CRUD 代表建立(Create)、讀取(Read)、更新(Update)、刪除(Delete)。在 3.0 版本中,我們還引入了 ListCrudRepository,它與 CrudRepository 非常相似,但對於返回多個實體的方法,它返回一個 List 而不是 Iterable,這可能更易於使用。

如果您正在使用響應式儲存,您可以選擇 ReactiveCrudRepositoryRxJava3CrudRepository,具體取決於您使用的響應式框架。

如果您正在使用 Kotlin,您可以選擇利用 Kotlin 協程的 CoroutineCrudRepository

此外,如果您需要允許指定 Sort 抽象(或在第一個情況下為 Pageable 抽象)的方法,您可以擴充套件 PagingAndSortingRepositoryReactiveSortingRepositoryRxJava3SortingRepositoryCoroutineSortingRepository。請注意,各種排序儲存庫不再像 Spring Data 3.0 之前的版本那樣擴充套件其各自的 CRUD 儲存庫。因此,如果您需要兩者的功能,則需要同時擴充套件這兩個介面。

如果您不想擴充套件 Spring Data 介面,也可以使用 @RepositoryDefinition 註解您的儲存庫介面。擴充套件其中一個 CRUD 儲存庫介面會公開一組完整的方法來操作您的實體。如果您希望選擇性地公開方法,請將您想要公開的方法從 CRUD 儲存庫複製到您的領域儲存庫中。這樣做時,您可以更改方法的返回型別。Spring Data 將盡可能尊重返回型別。例如,對於返回多個實體的方法,您可以選擇 Iterable<T>List<T>Collection<T> 或 VAVR 列表。

如果您的應用程式中的許多儲存庫應該具有相同的方法集,您可以定義自己的基介面以供繼承。此類介面必須使用 @NoRepositoryBean 進行註解。這可以防止 Spring Data 嘗試直接建立其例項並因無法確定該儲存庫的實體(因為它仍包含一個泛型型別變數)而失敗。

以下示例展示瞭如何選擇性地公開 CRUD 方法(在本例中為 findByIdsave

選擇性地公開 CRUD 方法
@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 模組繫結

  1. 如果儲存庫定義擴充套件了特定模組的儲存庫,則它是特定 Spring Data 模組的有效候選者。

  2. 如果領域類使用特定模組的型別註解進行註解,則它是特定 Spring Data 模組的有效候選者。Spring Data 模組接受第三方註解(例如 JPA 的 @Entity)或提供自己的註解(例如 Spring Data MongoDB 和 Spring Data Elasticsearch 的 @Document)。

以下示例展示了使用特定模組介面的儲存庫(在本例中為 JPA)

示例 1. 使用特定模組介面的儲存庫定義
interface MyRepository extends JpaRepository<User, Long> { }

@NoRepositoryBean
interface MyBaseRepository<T, ID> extends JpaRepository<T, ID> { … }

interface UserRepository extends MyBaseRepository<User, Long> { … }

MyRepositoryUserRepository 在其型別層次結構中擴充套件了 JpaRepository。它們是 Spring Data JPA 模組的有效候選者。

以下示例展示了使用泛型介面的儲存庫

示例 2. 使用泛型介面的儲存庫定義
interface AmbiguousRepository extends Repository<User, Long> { … }

@NoRepositoryBean
interface MyBaseRepository<T, ID> extends CrudRepository<T, ID> { … }

interface AmbiguousUserRepository extends MyBaseRepository<User, Long> { … }

AmbiguousRepositoryAmbiguousUserRepository 在其型別層次結構中僅擴充套件了 RepositoryCrudRepository。雖然在使用唯一的 Spring Data 模組時這沒有問題,但多個模組無法區分這些儲存庫應該繫結到哪個特定的 Spring Data 模組。

以下示例展示了使用帶註解的領域類的儲存庫

示例 3. 使用帶註解的領域類的儲存庫定義
interface PersonRepository extends Repository<Person, Long> { … }

@Entity
class Person { … }

interface UserRepository extends Repository<User, Long> { … }

@Document
class User { … }

PersonRepository 引用 Person,它用 JPA @Entity 註解進行註解,因此該儲存庫明確屬於 Spring Data JPA。UserRepository 引用 User,它用 Spring Data MongoDB 的 @Document 註解進行註解。

以下不良示例展示了使用帶混合註解的領域類的儲存庫

示例 4. 使用帶混合註解的領域類的儲存庫定義
interface JpaPersonRepository extends Repository<Person, Long> { … }

interface MongoDBPersonRepository extends Repository<Person, Long> { … }

@Entity
@Document
class Person { … }

此示例展示了一個使用 JPA 和 Spring Data MongoDB 註解的領域類。它定義了兩個儲存庫,JpaPersonRepositoryMongoDBPersonRepository。一個用於 JPA,另一個用於 MongoDB。Spring Data 無法再區分這些儲存庫,這會導致未定義的行為。

儲存庫型別詳細資訊區分領域類註解 用於嚴格的儲存庫配置,以識別特定 Spring Data 模組的儲存庫候選者。在同一個領域型別上使用多個持久化技術特定註解是可能的,並且可以在多種持久化技術中重用領域型別。但是,Spring Data 無法再確定要繫結儲存庫的唯一模組。

區分儲存庫的最後一種方法是透過限定儲存庫基本包。基本包定義了掃描儲存庫介面定義的起始點,這意味著儲存庫定義位於適當的包中。預設情況下,註解驅動配置使用配置類的包。基於 XML 配置中的基本包 是強制性的。

以下示例展示了基本包的註解驅動配置

基本包的註解驅動配置
@EnableJpaRepositories(basePackages = "com.acme.repositories.jpa")
@EnableMongoRepositories(basePackages = "com.acme.repositories.mongo")
class Configuration { … }
© . This site is unofficial and not affiliated with VMware.