介绍
本章将介绍 Spring Data 存储库的基本基础。在继续学习 JDBC 或 R2DBC 的具体内容之前,请确保您对这里解释的基本概念有扎实的理解。
Spring Data 仓库抽象的目标是显著减少为各种持久化存储实现数据访问层所需的样板代码量。
章节摘要
📄️ 核心概念
Spring Data 仓库抽象中的核心接口是 Repository。它将需要管理的领域类及其标识符类型作为类型参数。该接口主要充当标记接口,用于捕获要处理的类型,并帮助你发现扩展了此接口的其他接口。
📄️ 定义存储库接口
要定义仓库接口,首先需要定义一个特定于领域类的仓库接口。该接口必须扩展 Repository,并且要指定领域类和 ID 类型。如果你希望为该领域类型暴露 CRUD 方法,可以扩展 CrudRepository 或其变体,而不是 Repository。
📄️ 创建仓库实例
本节介绍如何为定义的仓库接口创建实例和 bean 定义。
📄️ 定义查询方法
仓库代理有两种方式可以从方法名称派生出特定于存储的查询:
📄️ 投影(Projections)
Spring Data 的查询方法通常返回由仓库管理的聚合根的一个或多个实例。然而,有时可能希望基于这些类型的某些属性创建投影。Spring Data 允许建模专用的返回类型,以便更有选择性地检索托管聚合的部分视图。
📄️ 对象映射基础
本节涵盖了 Spring Data 对象映射的基础知识,包括对象创建、字段和属性访问、可变性和不可变性。请注意,本节仅适用于不使用底层数据存储(如 JPA)对象映射的 Spring Data 模块。此外,请务必查阅特定存储的部分,了解特定于存储的对象映射,例如索引、自定义列或字段名称等。
📄️ 自定义转化
以下是一个 Spring 转换器的实现示例,它将字符串转换为自定义的 Email 值对象:
📄️ 自定义存储库实现
Spring Data 提供了多种选项,可以用很少的代码来创建查询方法。但当这些选项无法满足你的需求时,你也可以为仓库方法提供自定义的实现。本节将介绍如何做到这一点。
📄️ Spring Data 扩展
本节记录了一组 Spring Data 扩展,使得 Spring Data 能够在各种上下文中使用。目前,大多数集成都针对 Spring MVC。
📄️ 值表达式基础
值表达式是 Spring 表达式语言(SpEL)和属性占位符解析的结合体。它们将强大的编程表达式评估与简单的属性占位符解析相结合,以从环境(如配置属性)中获取值。
📄️ 按示例查询
本章介绍了示例查询(Query by Example)并解释了如何使用它。
📄️ 从聚合根发布事件
由仓库管理的实体是聚合根。在领域驱动设计(Domain-Driven Design,DDD)应用中,这些聚合根通常会发布领域事件。Spring Data 提供了一个名为 @DomainEvents 的注解,你可以将其用于聚合根的方法上,以便尽可能简化事件的发布,如下例所示:
📄️ 实体回调
Spring Data 基础设施提供了在调用某些方法之前和之后修改实体的钩子。这些所谓的 EntityCallback 实例提供了一种便捷的方式,以回调风格来检查和潜在地修改实体。EntityCallback 看起来非常像专门的 ApplicationListener。一些 Spring Data 模块会发布特定于存储的事件(例如 BeforeSaveEvent),这些事件允许修改给定的实体。在某些情况下,例如处理不可变类型时,这些事件可能会引发问题。此外,事件发布依赖于 ApplicationEventMulticaster。如果使用异步的 TaskExecutor 来配置它,可能会导致不可预测的结果,因为事件处理可能会被分叉到一个线程上。
📄️ 仓库方法的空值处理
自 Spring Data 2.0 起,返回单个聚合实例的仓库 CRUD 方法使用 Java 8 的 Optional 来表示可能缺失的值。除此之外,Spring Data 还支持在查询方法上返回以下包装类型:
📄️ 仓库查询关键词
下表列出了 Spring Data 仓库查询派生机制通常支持的主题关键字,用于表达谓词。由于某些关键字在特定存储中可能不受支持,请查阅具体存储的文档以获取支持的关键字的准确列表。
📄️ 仓库查询返回类型
下表列出了 Spring Data 仓库通常支持的返回类型。但是,请查阅特定存储的文档以获取支持的返回类型的准确列表,因为此处列出的某些类型可能在特定存储中不受支持。