CrudRepository Vs JpaRepository
CrudRepository Vs JpaRepository
在 Spring Data JPA 中, CrudRepository 和 JpaRepository 接口有什么区别?
当我在网上看到示例时,它们似乎可以互换使用。
它们之间有什么区别?
为什么你要使用一个而不是另一个呢?
肯恩的答案基本正确,但我想就你问题中的“你为什么要使用一个而不使用另一个?”发表一下我的看法。
基础知识
您选择的存储库的基本接口有两个主要目的。首先,您允许Spring Data存储库基础设施找到您的接口并触发代理创建,以便将接口的实例注入客户端。第二个目的是将所需的功能拉入接口中,而不必声明额外的方法。
常见接口
Spring Data核心库附带有两个公共基础接口,它们公开了一组专用功能:
CrudRepository
- CRUD方法PagingAndSortingRepository
- 用于分页和排序的方法(扩展CrudRepository
)
存储特定接口
各个存储模块(例如JPA或MongoDB)公开这些基础接口的存储特定扩展,以允许访问存储特定功能,例如考虑到一些存储细节的flushing或专用批处理。一个例子是JpaRepository
的deleteInBatch(...)
,它与delete(...)
不同,因为它使用查询来删除给定的实体,这更具性能,但会带来不触发JPA定义的级联效应的副作用(如规范定义的那样)。
我们通常建议不使用这些基础接口,因为它们将底层持久性技术暴露给客户端,从而加强了它们与存储库之间的关系。此外,您会远离存储库的初始定义,即“实体的集合”。因此,如果可能,请使用PagingAndSortingRepository
。
自定义存储库基础接口
直接依赖于提供的基础接口的缺点有两个。尽管两者都可能被认为是理论上的问题,但我认为它们覆盖面很广,因此必须意识到:
- 依赖于Spring Data存储库接口会使您的存储库接口与该库耦合在一起。我认为这不是一个特别的问题,因为您的代码中可能会使用像
Page
或Pageable
这样的抽象。Spring Data与像commons-lang或Guava这样的任何其他通用库没有任何不同。只要提供合理的效益,就可以接受它。 - 通过扩展
CrudRepository
等,您可以一次性公开完整的持久性方法。这在大多数情况下也可能是可以的,但您可能会遇到您想要更细粒度地控制公开的方法的情况,例如创建不包括CrudRepository
的save(...)
和delete(...)
方法的ReadOnlyRepository
。
解决这两个缺点的方法是编制自己的基础存储库接口,甚至是一组它们。在我看来,许多应用程序都是这样的:
interface ApplicationRepositoryextends PagingAndSortingRepository { } interface ReadOnlyRepository extends Repository { // Al finder methods go here }
第一个存储库接口是一些通用的基本接口,实际上只修复点1,但也将ID类型绑定为 Long
以保持一致性。第二个接口通常具有从 CrudRepository
和 PagingAndSortingRepository
复制的所有 find…(…)
方法,但不公开操作方法。有关该方法的更多信息,请在参考文档中阅读。
摘要 - tl; dr
存储库抽象允许您完全基于您的架构和功能需求选择基础存储库。如果它们适合,请使用提供的开箱即用的存储库,如果必要,可以制作自己的存储库基本接口。除非不可避免,否则请远离特定于存储库的存储库接口。
JpaRepository
扩展自 PagingAndSortingRepository
,而 PagingAndSortingRepository
又扩展自 CrudRepository
。
它们的主要功能是:
CrudRepository
主要提供 CRUD 函数。PagingAndSortingRepository
提供分页和排序记录的方法。JpaRepository
提供一些与 JPA 相关的方法,例如刷新持久性上下文和批量删除记录。
由于以上继承关系,JpaRepository
将拥有 CrudRepository
和 PagingAndSortingRepository
的所有功能。因此,如果您不需要仓库具备 JpaRepository
和 PagingAndSortingRepository
提供的功能,请使用 CrudRepository
。