Spring JPA 存储库接口定义

时间:2022-07-24
本文章向大家介绍Spring JPA 存储库接口定义,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

Spring JPA 定义接口

翻译:Defining Repository Interfaces

​ 首先,定义一个特定的实体类的存储库接口,这个接口必须继承自Repository并且绑定对应的实体类和主键ID类型。如果想要引用并使用该实体类的CRUD方法,要继承CrudRepository而不是继承Repository

微调存储库接口定义

	通常,您的存储库接口扩展自`repository`、`CrudRepository`或`PagingAndSortingRepository`。但如果不想扩展Spring数据接口,也可以用`@RepositoryDefinition`为存储库接口添加注释。扩展`CrudRepository`接口中公开的一整套操作实体的方法。如果您希望对要公开的方法有选择性暴露,请将要选择性公开的方法从`CrudRepository`复制到域存储库中。

这样做可以让您在提供的Spring数据存储库功能之上拓展自己的抽象方法。

​ 下面的例子展示了如何选择性的继承并暴露CrudRepository接口方法:

例7:选择性的暴露CRUD方法

@NoRepositoryBean
interface MyBaseRepository<T, ID> extends Repository<T, ID> {

  Optional<T> findById(ID id);

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

interface UserRepository extends MyBaseRepository<User, Long> {
  User findByEmailAddress(EmailAddress emailAddress);
}

TIPS :这样子引入,只可以使用在该接口中被定义的方法,即选择性exposed,UserRepository是自定义的接口

​ 在前面的示例中,您为所有域存储库定义了一个通用的基本接口,并公开了findById(…)save(…)。这些方法被路由到Spring Data提供的您选择的存储的基本存储库实现中(例如,如果您使用JPA,则实现是SimpleJpaRepository),因为它们与CrudRepository中的方法签名匹配。因此,UserRepository现在可以保存用户,按ID查找单个用户,并触发一个按电子邮件地址查找用户的查询。

findById 是 CrudRepository提供的方法 ,findByEmailAddress是自定的暴露方法

将存储库和多个Spring Data 模块一起使用

​ 在你的应用中使用一个唯一的Spring Data模块会使事情变得简单,因为定义范围内的所有存储库接口都会绑定到Spring Data模块。有时,应用需要使用不只一个Spring Data模块。在这种情况下,存储库必须进行持久性技术区分。当它在类路径上检测到多个存储库工厂方法时,Spring数据进入严格的存储库配置模式。使用严格的配置信息来确定存储库定义的Spring数据模块绑定:

  1. 如果存储库定义扩展了特定于模块的存储库,那么它是特定Spring数据模块的有效候选。
  2. 如果域类是用特定于模块的类型注释注释的,那么它是特定Spring数据模块的有效候选。提供第三方数据的注解(比如Spring的@Document注解和第三方的Jpa数据注解@Entity)。 ​ 以下示例显示了使用特定于模块的接口(在本例中为JPA)的存储库:

例8:使用模块特定接口的存储库定义

interface MyRepository extends JpaRepository<User, Long> { }

@NoRepositoryBean
interface MyBaseRepository<T, ID> extends JpaRepository<T, ID> { … }

interface UserRepository extends MyBaseRepository<User, Long> { … }

MyRepository和UserRepository在其类型层次结构中扩展了JpaRepository。它们是springdatajpa模块的有效候选者。

以下示例显示了使用通用接口的存储库:

例9:使用通用接口的存储库定义

interface AmbiguousRepository extends Repository<User, Long> { … }

@NoRepositoryBean
interface MyBaseRepository<T, ID> extends CrudRepository<T, ID> { … }

interface AmbiguousUserRepository extends MyBaseRepository<User, Long> { … }

AmbiguousRepository和ambiguousserrepository在其类型层次结构中只扩展Repository和CrudRepository。当使用一个唯一的Spring数据模块时,这是非常好的,但是多个模块无法区分这些存储库应该绑定到哪些特定的Spring数据。

以下示例显示了使用带批注的域类的存储库:

例10:使用域类和注释的存储库定义

interface PersonRepository extends Repository<Person, Long> { … }

@Entity
class Person { … }

interface UserRepository extends Repository<User, Long> { … }

@Document
class User { … }

PersonRepository引用Person,Person用JPA@Entity注释进行了注释,因此这个存储库显然属于springdatajpa。UserRepository引用了User,它用springdatamongodb的@Document注释进行了注释。

以下错误示例显示了一个存储库,该存储库使用带有混合批注的域类:

例11:使用具有混合注释的域类的存储库定义(错误示例)

interface JpaPersonRepository extends Repository<Person, Long> { … }

interface MongoDBPersonRepository extends Repository<Person, Long> { … }

@Entity
@Document
class Person { … }

这个例子展示了一个使用JPA和springdatamongodb注释的域类。它定义了两个存储库:JpaPersonRepository和MongoDBPersonRepository。一个用于JPA,另一个用于MongoDB。Spring数据不再能够区分存储库,这会导致未定义的行为。

​ 存储库类型详细信息和区分域类注释用于严格的存储库配置,以识别特定Spring数据模块的存储库候选。在同一个域类型上使用多个特定于持久性技术的注释是可能的,并且可以跨多个持久性技术重用域类型。但是,Spring数据就不能再确定与存储库绑定的唯一模块。,区分存储库的最后一种方法是确定存储库基本包的范围。基本包定义了扫描存储库接口定义的起点,这意味着存储库定义位于适当的包中。默认情况下,注释驱动配置使用configuration类的包。基于XML的配置中的基本包是必需的。,以下示例显示基本包的注释驱动配置:

以下示例显示基本包的注释驱动配置:

例12:基本包的注释驱动配置

@EnableJpaRepositories(basePackages = "com.acme.repositories.jpa")
@EnableMongoRepositories(basePackages = "com.acme.repositories.mongo")
class Configuration { … }