CrudRepository和JpaRepository接口在Spring Data JPA中有什么区别?
CrudRepository和JpaRepository接口在Spring Data JPA中有什么区别?
Spring Data JPA中的CrudRepository和JpaRepository接口有什么区别?
当我在网上看到示例时,它们似乎可以互换使用。
它们之间的区别是什么?
为什么您会选择一个而不选择另一个?
肯恩的回答基本正确,但我想就您问题中的“为什么要使用其中一个而不是另一个?”部分发表意见。
基础知识
您选择的基本接口有两个主要目的。首先,您允许Spring Data仓库基础设施找到您的接口并触发代理创建,以便您将接口的实例注入到客户端中。第二个目的是将所需的功能尽可能地收入到接口中,而不需要声明额外的方法。
常用接口
Spring Data核心库附带两个基本接口,它们公开了一个专用的功能集:
CrudRepository
- CRUD方法PagingAndSortingRepository
- 分页和排序方法(扩展了CrudRepository
)
存储特定接口
各个存储模块(例如JPA或MongoDB)公开了这些基本接口的存储特定扩展,以允许访问存储特定功能,例如考虑某些存储特定内容的刷新或专用批处理。这的一个例子就是 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
,而后者则扩展了 CrudRepository
。
它们的主要功能如下:
CrudRepository
主要提供CRUD函数。PagingAndSortingRepository
提供了对记录进行分页和排序的方法。JpaRepository
提供了一些JPA相关的方法,例如刷新持久化上下文和批量删除记录。
由于上述继承,JpaRepository
将具有CrudRepository
和PagingAndSortingRepository
提供的所有功能。因此,如果您不需要存储库具有JpaRepository
和PagingAndSortingRepository
提供的函数,请使用CrudRepository
。