Spring Data 3.0 版本 ListCrudRepository 及相關功能發布公告

工程 | Jens Schauder | 2022 年 2 月 22 日 | ...

Spring Data 的 CrudRepository 具有多種方法,可以傳回由 repository 管理的實體的複數實例。它透過使用 Iterable 而非 List 來達成,如同人們可能預期的那樣。在許多情況下,這並不重要,因為您通常無論如何都想迭代結果。然而,您偶爾可能偏好 List。在這些情況下,Iterable 就令人感到困擾。

我將撰寫更多關於最初為何做出此選擇,以及在您使用 Spring Data 2.x 期間如何處理它的文章。然而,先讓我發布好消息

Repository 傳回 List

Spring Data 3.0.0 現在在最新的快照版本中提供了 ListCrudRepository,它在 CrudRepository 傳回 Iterable 的地方傳回 List

範例 1. CrudRepository 與 ListCrudRepository 的比較

@NoRepositoryBean
public interface CrudRepository<T, ID> extends Repository<T, ID> {

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

	<S extends T> Iterable<S> saveAll(Iterable<S> entities);

	Optional<T> findById(ID id);

	boolean existsById(ID id);

	Iterable<T> findAll();

	Iterable<T> findAllById(Iterable<ID> ids);

	long count();

	void deleteById(ID id);

	void delete(T entity);

	void deleteAllById(Iterable<? extends ID> ids);

	void deleteAll(Iterable<? extends T> entities);

	void deleteAll();
}

@NoRepositoryBean
public interface ListCrudRepository<T, ID> extends CrudRepository<T, ID> {

	<S extends T> List<S> saveAll(Iterable<S> entities);

	List<T> findAll();

	List<T> findAllById(Iterable<ID> ids);
}

分割排序 Repository

廣受歡迎的 PagingAndSortingRepository 過去是從 CrudRepository 擴展而來,但現在已不再如此。這讓您可以將其與 CrudRepositoryListCrudRepository 或您自己建立的基礎介面結合使用。這表示您現在必須明確地從 CRUD 片段擴展,即使您已經從 PagingAndSortingRepository 擴展也是如此。

範例 2. 分頁和排序 repository — 2.x 版本

public interface PersonRepository<Person, Long> extends PagingAndSortingRepository<Person, Long> {}

範例 3. 分頁和排序 repository — 3.x 版本

public interface PersonRepository<Person, Long> extends PagingAndSortingRepository<Person, Long>, ListCrudRepository<Person, Long> {}

還有其他介面會傳回 Iterable<T>,現在也獲得了傳回 List<T> 的配套介面。

片段介面傳回 Iterable

新的片段介面傳回 List

QuerydslPredicateExecutor

ListQuerydslPredicateExecutor

QueryByExampleExecutor

ListQueryByExampleExecutor

此外,與 PagingAndSortingRepository 類似,其他排序 repository 介面過去會擴展其各自的 CRUD 變體,但現在已不再如此。

排序片段介面

它不再擴展的 CRUD repository

ReactiveSortingRepository

ReactiveCrudRepository

CoroutineSortingRepository

CoroutineCrudRepository

Rx3JavaSortingRepository

Rx3JavaCrudRepository

這表示,當您使用這些介面中的任何一個作為 Spring Data repository 的基礎時,您現在需要額外擴展各自的 CRUD repository(假設您實際上對使用它的 CRUD 功能感興趣)。

關於 2.x 版本?

如果您尚未準備好跳到 3.0.0 快照版本,您仍然可以使用所有現有的選項來避免處理 Iterable 作為傳回值的情況。

  1. 您不需要擴展 CrudRepository。您可以改用 Repository,它沒有任何方法。現在您可以僅新增您實際想要的方法,並使用您想要的傳回類型。如果它們與 CrudRepository 中的類型相符,但傳回 CollectionList 而非 Iterable,Spring Data 會為您處理轉換。此外,在大多數情況下,您可能實際上不需要在生產環境中使用 deleteAll,對吧?

  2. 如果您想要 CrudRepository 的所有方法,但希望將 Iterable 替換為其他內容,您可以透過擴展 CrudRepository 並覆寫您想要變更的方法來實現。

  3. 為了避免在您宣告的每個 repository 介面中都執行此操作,您可以建立您自己的基礎 repository 介面。對於這種方法,請使用與上述相同的方法,但使用 @NoRepositoryBean 進行註解,以便 Spring Data 不會嘗試為其建立實作。您實際的 repository 介面現在可以從此介面擴展。廣受歡迎的 JpaRepository 就是這樣一個介面。

  4. 與上述方法相同,您可以使用 Streamable 作為傳回類型,它是一個 Iterable,但提供直接轉換方法為 StreamListSet

  5. 如果您不想修改 repository,您可以使用 StreamableIterable 轉換StreamListSet 的介面。

最初為何選擇 Iterable?

  1. CrudRepository 的方法需要由每個 Spring Data 實作來實作。因此,它不僅是 Spring Data 使用者的 API,也是提供 Spring Data 模組的人員的 SPI。此外,這樣的模組可能不想在傳回之前填滿完整的列表,而是希望快速傳回 Iterable,同時仍在載入和處理資料。

  2. 如果 CrudRepository 傳回 List,您將無法覆寫其方法以傳回 StreamableSetCollectionIterable

  3. Streamable 本來會是一個很棒的傳回類型,因為它結合了彈性和可用性。不幸的是,它會將 Spring 介面強加於您的領域模型中,這被許多人認為是不可接受的,或至少是一種程式碼異味。

此外,一旦 Iterable 出現,就變得難以甚至不可能在不破壞現有程式碼的情況下變更 API。因此,找到一個具有更好可用性,同時限制變更造成的破壞的解決方案花費了一些時間。

我們希望您喜歡這個解決方案,並且我們相信您會讓我們知道您的想法。

取得 Spring 電子報

隨時掌握 Spring 電子報的最新資訊

訂閱

領先一步

VMware 提供培訓和認證,以加速您的進展。

了解更多

取得支援

Tanzu Spring 在一個簡單的訂閱中提供 OpenJDK™、Spring 和 Apache Tomcat® 的支援和二進位檔案。

了解更多

即將到來的活動

查看 Spring 社群中所有即將到來的活動。

查看全部