JpaRepository
扩展自 PagingAndSortingRepository
,而 PagingAndSortingRepository
又扩展自 CrudRepository
。
它们的主要功能如下:
CrudRepository
提供了CRUD(增删改查)函数。PagingAndSortingRepository
提供将记录进行分页和排序的方法。JpaRepository
提供了一些与 JPA 相关的方法,例如刷新持久化上下文并批量删除记录。由于上述继承关系,JpaRepository
将具有 CrudRepository
和 PagingAndSortingRepository
提供的所有功能。因此,如果您不需要存储库具有 JpaRepository
和 PagingAndSortingRepository
提供的功能,请使用 CrudRepository
。
肯的答案基本正确,但我想在你问题中的“为什么要使用其中之一?”方面发表一下意见。
您选择的存储库的基本接口具有两个主要目的。首先,允许Spring Data存储库基础设施找到您的接口并触发代理创建,以便将接口实例注入客户端。第二个目的是将所需功能尽可能多地引入接口,而无需声明额外的方法。
Spring Data核心库附带了两个基础接口,公开了一组专用功能:
CrudRepository
- CRUD方法PagingAndSortingRepository
- 分页和排序方法(扩展CrudRepository
)各个存储模块(例如JPA或MongoDB)公开了这些基础接口的存储特定扩展,以允许访问存储特定功能,如考虑某些存储细节的刷新或专用批处理。其中一个示例是JpaRepository
的deleteInBatch(…)
,它与delete(…)
不同,因为它使用查询来删除给定的实体,这更有效率,但具有不触发JPA定义的级联(按规范定义)的副作用。
我们通常建议不使用这些基础接口,因为它们将底层持久性技术暴露给客户端,从而加强了它们与存储库之间的耦合性。此外,您会远离存储库的原始定义,即“一组实体”,所以如果您可以,请使用PagingAndSortingRepository
。
直接依赖于提供的基础接口的缺点是双重的。虽然这两个可能被视为理论,但我认为它们很重要,需要意识到:
Page
或Pageable
等抽象。 Spring Data与commons-lang或Guava等其他通用库没有任何区别。只要它提供合理的好处,就没问题。CrudRepository
,您一次性公开了完整的持久性方法集。这在大多数情况下也可能是好的,但您可能会遇到希望更细粒度地控制公开方法的情况,例如创建一个不包括CrudRepository
的save(…)
和delete(…)
方法的ReadOnlyRepository
。应对这两个缺点的解决方案是制作自己的基本存储库接口甚至一组这样的接口。在许多应用程序中,我看到了这样的东西:
interface ApplicationRepository<T> extends PagingAndSortingRepository<T, Long> { }
interface ReadOnlyRepository<T> extends Repository<T, Long> {
// Al finder methods go here
}
Long
以保持一致性。第二个接口通常从CrudRepository
和PagingAndSortingRepository
中复制所有find…(…)
方法,但不公开操纵这些方法。在参考文档中阅读更多有关该方法的信息。CrudRepository
和JpaRepository
之间的区别:
CrudRepository
CrudRepository
是一个基础接口,继承了Repository
接口。CrudRepository
主要提供CRUD(创建、读取、更新、删除)操作。saveAll()
方法的返回类型为Iterable
。CrudRepository
的存储库以执行CRUD操作。JpaRepository
JpaRepository
扩展了PagingAndSortingRepository
,后者又扩展了CrudRepository
。JpaRepository
提供了CRUD和分页操作,还提供了其他方法,如flush()
、saveAndFlush()
和deleteInBatch()
等。saveAll()
方法的返回类型为List
。JpaRepository
的存储库以执行CRUD和批量操作。spring-data-jpa 3.x
从现在开始使用spring-boot 3.x
和spring-core 6.x
与spring-data-jpa 3.x
,结构和层次结构已经修改,看起来更清晰。
ListCrudRepository
扩展了CrudRepository
ListPagingAndSortingRepository
扩展PagingAndSortingRepository
JpaRepository
同时扩展了ListCrudRepository
和ListPagingAndSortingRepository
。
因此,基本上ListPagingAndSortingRepository
和ListCrudRepository
这两个新引入的接口现在代表旧接口的功能,但返回类型为List<T>
,而剩余的PagingAndSortingRepository
和CrudRepository
则处理Iterable<T>
类型的返回值。
在新版本(3.x)中,结构如下:
在过去(3.0之前),许多声明返回List<T>
的方法直接在JpaRepository
中声明,但现在这些方法已被提取到ListPagingAndSortingRepository
和ListCrudRepository
中。
因此,在3.x版本之前的结构如下:
我希望从上面的图表中清楚地了解如何在3.x
版本中修改所提到的JpaRepository
和CrudRepository
。
2.x
版本迁移到 3.x
版本(如果您从 spring-boot 2.x
迁移到 spring-boot 3.x
,则必须这样做),如上图所示,您应该预期在您的代码中使用了 PagingAndSortingRepository
的情况下会有破坏性代码,因为过去它是从 CrudRepository
继承的,因此直接扩展 PagingAndSortingRepository
的自定义存储库已经能够访问 CrudRepository
的方法。如果出现此问题,您应该通过调整自定义存储库以扩展 ListCrudRepository
或 CrudRepository
来解决此问题。所有答案都提供了足够的细节来回答问题。但是,让我添加更多的内容。
为什么要使用这些接口:
每个接口的作用:
何时使用哪个接口:
根据 http://jtuts.com/2014/08/26/difference-between-crudrepository-and-jparepository-in-spring-data-jpa/
通常最好根据是否需要排序和分页来使用 CrudRepository 或 PagingAndSortingRepository 。
如果可能的话,应该避免使用JpaRepository,因为它将您的存储库与JPA持久性技术绑定在一起,在大多数情况下,您可能甚至不会使用它提供的额外方法。
Spring Data JPA提供了JpaRepository
和CrudRepository
接口,以简化JPA应用程序中数据访问库的创建。
CrudRepository
是具有基本CRUD(创建、读取、更新、删除)操作的实体的基本接口。CrudRepository
提供了一组最小的方法,如save()
、findAll()
、findById()
、delete()
等,并可以通过其他自定义方法进行扩展。
这是代码示例:
public interface PersonEntityRepository extends CrudRepository<PersonEntity, Long> {
}
JpaRepository
接口扩展了 CrudRepository
接口。
JpaRepository
接口提供了其他基本 CRUD 操作之外的附加方法,例如:
findAll(Sort sort)
- 返回按给定条件排序的所有实体的方法。findAll(Pageable pageable)
- 根据给定的分页和排序条件返回一个实体页面的方法。flush()
- 将所有待处理更改刷新到数据库的方法。saveAndFlush(T entity)
- 保存实体并立即将更改刷新到数据库的方法。
这是代码示例:public interface PersonEntityRepository extends JpaRepository<PersonEntity, Long> {
List<TestEntity> findByName(String name);
List<Employee> findByAgeGreaterThan(double age);
}
CrudRepository
接口进行基本的 CRUD 操作,使用 JpaRepository
接口进行更高级的功能,如分页、排序和立即将更改刷新到数据库。Crud Repository是基础接口,充当标记接口。
JPA repository也扩展了PagingAndSorting repository。它提供了所有有用于实现分页的方法。Crud Repository不提供实现分页和排序的方法。
CrudRepository
不是一个标记接口。在代码中也很少(可能为0)检查它的实例,因此它也不起到标记接口的作用。 - Jens Schauder