|
该版本仍在开发中,尚未被视为稳定。对于最新稳定版本,请使用Spring Data Elasticsearch 5.5.5! |
定义仓库接口
要定义仓库接口,首先需要定义一个领域类别特定的仓库接口。
接口必须扩展存储 库并将类型化为域类和ID类型。
如果你想为该领域类型暴露CRUD方法,可以扩展原油仓库,或其变体之一,代替存储 库.
微调仓库定义
你可以用几种方式开始使用仓库界面。
典型的做法是延长原油仓库,它提供了CRUD功能的方法。
CRUD代表创建(Create)、阅读(Read)、更新(Update)、删除(Delete)。
3.0版本我们也引入了ListCrudRepository这与原油仓库但对于返回多个实体的方法,它返回列表而不是可迭代你可能会觉得这样更容易使用。
如果你用的是响应式商店,可能会选择ReactiveCrudRepository或RxJava3CrudRepository这取决于你使用的响应式框架。
如果你用的是Kotlin,可能会选CoroutineCrudRepository该程序利用了 Kotlin 的协程。
此外,你还可以延长分页与排序仓库,ReactiveSortingRepository,RxJava3SortingRepository或CoroutineSortingRepository如果你需要允许指定排序抽象,或者在第一种情况下是a可页面抽象化。
请注意,各排序仓库不再像 Spring Data 版本 3.0 之前那样扩展了各自的 CRUD 仓库。
因此,如果你想同时拥有两个接口的功能,就需要同时扩展两个接口。
如果你不想扩展 Spring Data 接口,也可以在仓库接口上标注@RepositoryDefinition.
扩展CRUD仓库接口后,可以暴露出一套作实体的完整方法。
如果你更愿意选择暴露的方法,可以把你想暴露的方法从CRUD仓库复制到你的域仓库。
在此过程中,你可以更改返回方法的类型。
Spring Data 会尽可能保留返回类型。
例如,对于返回多个实体的方法,你可以选择可迭代(Iterable<T>,List<T>,收藏书<T>或者VAVR名单。
如果你的应用中有多个仓库都应该有相同的方法集,你可以自定义自己的基础接口来继承。
这样的接口必须注释为@NoRepositoryBean.
这防止了 Spring Data 尝试直接创建该实例而失败,因为它无法确定该仓库的实体,因为它仍然包含一个通用类型的变量。
以下示例展示了如何有选择地暴露CRUD方法(findById和救,在此例中):
@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);
}
在之前的例子中,你为所有域仓库定义了一个通用的基接口,并公开了findById(...)以及保存(...).这些方法会被路由到你选择的Spring Data提供的基础仓库实现中(例如,如果你使用JPA,实现是SimpleJpaRepository),因为它们与 的方法签名匹配原油仓库.
所以用户仓库现在可以保存用户,按ID查找个别用户,并触发查询查找用户通过电子邮件地址。
中间仓库接口标注为@NoRepositoryBean.
确保在所有 Spring Data 不该在运行时创建实例的仓库接口中添加该注释。 |
使用带有多个 Spring 数据模块的仓库
在你的应用中使用独特的 Spring Data 模块会让事情变得简单,因为定义范围内的所有仓库接口都绑定在 Spring Data 模块上。 有时,应用程序需要使用多个 Spring Data 模块。 在这种情况下,仓库定义必须区分持久化技术。 当 Spring Data 检测到类路径上有多个仓库工厂时,会进入严格的仓库配置模式。 严格配置利用仓库或域类的详细信息来决定仓库定义的 Spring Data 模块绑定:
以下示例展示了使用模块特定接口(此处为JPA)的仓库:
interface MyRepository extends JpaRepository<User, Long> { }
@NoRepositoryBean
interface MyBaseRepository<T, ID> extends JpaRepository<T, ID> { … }
interface UserRepository extends MyBaseRepository<User, Long> { … }
我的仓库和用户仓库扩展JpaRepository在它们的类型层级中。
它们是Spring Data JPA模块的有效候选。
以下示例展示了使用通用接口的仓库:
interface AmbiguousRepository extends Repository<User, Long> { … }
@NoRepositoryBean
interface MyBaseRepository<T, ID> extends CrudRepository<T, ID> { … }
interface AmbiguousUserRepository extends MyBaseRepository<User, Long> { … }
模糊仓库和模糊用户仓库仅限延伸存储 库和原油仓库在它们的类型层级中。
虽然在使用独特的Spring Data模块时这样做没问题,但多个模块无法区分这些仓库应绑定到哪个特定的Spring Data。
以下示例展示了一个使用带注释的域类的仓库:
interface PersonRepository extends Repository<Person, Long> { … }
@Entity
class Person { … }
interface UserRepository extends Repository<User, Long> { … }
@Document
class User { … }
PersonRepository引用人,并用JPA注释@Entity注释,因此该仓库显然属于 Spring Data JPA。用户仓库引用用户,并用Spring Data MongoDB的注释@Document注解。
以下这个糟糕的例子展示了一个使用带有混合注释的域类的仓库:
interface JpaPersonRepository extends Repository<Person, Long> { … }
interface MongoDBPersonRepository extends Repository<Person, Long> { … }
@Entity
@Document
class Person { … }
这个例子展示了一个域类,同时使用了JPA和Spring Data MongoDB的注释。
它定义了两个仓库,JpaPersonRepository和MongoDBPersonRepository.
一个用于 JPA,另一个用于 MongoDB。
Spring Data 不再能区分这些仓库,导致行为不明确。
存储库类型细节和区分域类注释用于严格的存储库配置,以识别特定 Spring Data 模块的存储库候选。 在同一域类型上使用多个持久化技术专用的注释是可能的,并允许在多个持久化技术间重复使用领域类型。 然而,Spring Data 无法再确定唯一模块来绑定仓库。
区分仓库的最后一种方法是对仓库基础包进行范围。 基础包定义了扫描仓库接口定义的起点,这意味着仓库定义位于相应的包中。 默认情况下,注释驱动配置使用配置类的包。 基于XML配置的基础包是必备的。
以下示例展示了基于注释驱动的基础包配置:
@EnableJpaRepositories(basePackages = "com.acme.repositories.jpa")
@EnableMongoRepositories(basePackages = "com.acme.repositories.mongo")
class Configuration { … }