领先一步
VMware 提供培训和认证,以加速您的进步。
了解更多Spring Data 的 CrudRepository
具有多种返回存储库管理的实体多个实例的方法。它通过使用 Iterable
而不是像预期的那样使用 List
来实现。在许多情况下,这无关紧要,因为您通常无论如何都希望迭代结果。但是,您有时可能更喜欢 List
。在这些情况下,Iterable
令人烦恼。
我将详细介绍为什么最初做出这样的选择以及如何在 Spring Data 2.x 上处理它。但是,让我先说一下好消息
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);
}
流行的 PagingAndSortingRepository
过去扩展自 CrudRepository
,但现在不再扩展了。这使您可以将其与 CrudRepository
或 ListCrudRepository
或您自己创建的基本接口结合使用。这意味着您现在必须显式地扩展自 CRUD 片段,即使您已经扩展自 PagingAndSortingRepository
。
示例 2. 分页和排序存储库 - 版本 2.x
public interface PersonRepository<Person, Long> extends PagingAndSortingRepository<Person, Long> {}
示例 3. 分页和排序存储库 - 版本 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
,其他排序存储库接口过去扩展自它们各自的 CRUD 变体,但现在不再这样做。
排序片段接口
它不再扩展的 CRUD 存储库
ReactiveSortingRepository
CoroutineSortingRepository
CoroutineCrudRepository
Rx3JavaSortingRepository
这意味着,当您使用这些接口中的任何一个作为 Spring Data 存储库的基础时,您现在需要额外扩展相应的 CRUD 存储库(假设您实际上有兴趣使用它的 CRUD 功能)。
如果您还没有准备好切换到 3.0.0 快照版本,您仍然可以使用所有 现有选项 来避免处理 Iterable
作为返回值。
您无需扩展 CrudRepository
。您可以改为使用 Repository
,它没有任何方法。现在,您可以仅添加实际需要的方法以及所需的返回类型。如果它们与 CrudRepository
中的方法匹配,但返回 Collection
或 List
而不是 Iterable
,Spring Data 会为您处理转换。此外,在大多数情况下,您可能真的不需要在生产环境中使用 deleteAll
,对吧?
如果您想要 CrudRepository
的所有方法,但希望将 Iterable
替换为其他内容,您可以通过扩展 CrudRepository
并覆盖要更改的方法来实现。
无需在声明的每个存储库接口中执行此操作,您可以创建自己的基本存储库接口。对于这种方法,请使用与上述相同的方法,但使用 @NoRepositoryBean
注释它,以便 Spring Data 不尝试为此创建实现。您实际的存储库接口现在可以扩展自此接口。流行的 JpaRepository
就是这样的一个接口。
与上述相同的方式,您可以使用 Streamable
作为返回类型,它是一个 Iterable
,但提供了 直接转换为 Stream
的方法、List
和 Set
。
如果您不想触碰存储库,您可以使用 Streamable
将 Iterable
转换为 Stream
、List
或 Set
的接口。
CrudRepository
的方法需要由每个 Spring Data 实现来实现。因此,它不仅是 Spring Data 用户的 API,也是为提供 Spring Data 模块的人员提供的 SPI。此外,此类模块可能不希望在返回之前填充完整列表,而是希望快速返回 Iterable
,同时仍然加载和处理数据。
如果 CrudRepository
返回 List
,则您无法覆盖其方法以返回 Streamable
、Set
、Collection
或 Iterable
。
Streamable
本可以成为一个很好的返回类型,因为它结合了灵活性和可用性。不幸的是,它会将 Spring 接口强制到您的领域模型中,许多人认为这是不可取的,或者至少是一种代码异味。
此外,一旦 Iterable
发布,更改 API 就会变得困难甚至不可能,因为这会导致现有代码中断。因此,找到一种在限制更改导致的破坏的同时提高可用性的解决方案需要一些时间。
我们希望您喜欢这个解决方案,并且相信您会告诉我们您的想法。