Spring Data Release Gosling 有什么新内容?

一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / Java 学习路线 / 一对一提问 / 学习打卡/ 赠书活动

目前,正在 星球 内带小伙伴们做第一个项目:全栈前后端分离博客项目,采用技术栈 Spring Boot + Mybatis Plus + Vue 3.x + Vite 4手把手,前端 + 后端全栈开发,从 0 到 1 讲解每个功能点开发步骤,1v1 答疑,陪伴式直到项目上线,目前已更新了 204 小节,累计 32w+ 字,讲解图:1416 张,还在持续爆肝中,后续还会上新更多项目,目标是将 Java 领域典型的项目都整上,如秒杀系统、在线商城、IM 即时通讯、权限管理等等,已有 870+ 小伙伴加入,欢迎点击围观

在 12 个项目中修复了 300 多个问题,因此很难跟踪自上次发布以来发生的事情。所以这里是我们在上一次迭代中一直在做的一些新功能的更详细的摘录。

Ad-Hoc JPA 获取图表。

自从 Dijkstra 发布系列以来,我们已经能够通过 JPA 支持的存储库中的 @EntityGraph 注释引用在实体上声明的命名实体图。在下面的示例中,这会强制急切加载 firstname 和 lastname,而所有其他的则保持延迟加载。


 @Entity
@NamedEntityGraphs(
  @NamedEntityGraph(name = "with-tags",
    attributeNodes = { @NamedAttributeNode("tags") }))
class Product {

@ManyToMany Set<Tag> tags;

// other properties omitted }

interface ProductRepository extends Repository<Customer, Long> {

@EntityGraph("with-tags") Product findOneById(Long id); }

Gosling 版本现在将我们的 JPA 2.1 故事向前推进了一步,将其扩展到临时获取图形定义。通过在查询方法上通过 @EntityGraph(attributePaths = …) 显式指定属性,您不需要在实体上使用 NamedEntityGraph 注释。


 @Entity
@NamedEntityGraphs(
  @NamedEntityGraph(name = "with-tags",
    attributeNodes = { @NamedAttributeNode("tags") }))
class Product {

@ManyToMany Set<Tag> tags;

// other properties omitted }

interface ProductRepository extends Repository<Customer, Long> {

@EntityGraph("with-tags") Product findOneById(Long id); }

查询网络支持

Spring Data Web 支持已经允许您在控制器处理程序方法中声明 Pageable 类型的参数。新引入的 Querydsl 集成扩展了它,允许您接收直接从 HTTP 请求的查询字符串派生的准备好使用的 Predicate 。当配置了 @EnableSpringDataWebSupport 并且在类路径中找到 Querydsl 时,该功能会自动启用。

如果在没有进一步配置的情况下使用 Predicate 我们将尝试从方法的返回类型中解析 Predicate 解析的根类型,尽管在大多数情况下,通过 @QuerydslPredicate(root = …) 显式声明所需的类型引用可能更好。有了它,查询字符串属性绑定到创建例如的类型的匹配属性


 @Entity
@NamedEntityGraphs(
  @NamedEntityGraph(name = "with-tags",
    attributeNodes = { @NamedAttributeNode("tags") }))
class Product {

@ManyToMany Set<Tag> tags;

// other properties omitted }

interface ProductRepository extends Repository<Customer, Long> {

@EntityGraph("with-tags") Product findOneById(Long id); }

来自 ?firstname=Dave&lastname=Matthews 使用默认属性类型依赖绑定。


 @Entity
@NamedEntityGraphs(
  @NamedEntityGraph(name = "with-tags",
    attributeNodes = { @NamedAttributeNode("tags") }))
class Product {

@ManyToMany Set<Tag> tags;

// other properties omitted }

interface ProductRepository extends Repository<Customer, Long> {

@EntityGraph("with-tags") Product findOneById(Long id); }

现在使用默认(等于)绑定并不总是有意义,而是每个属性或特定类型的专用绑定。要实现这一点,只需提供一个 QuerydslBinderCustomizer 可以通过 @QuerydslPredicate(bindings = …) 注册,也可以简单地由存储库实现。


 @Entity
@NamedEntityGraphs(
  @NamedEntityGraph(name = "with-tags",
    attributeNodes = { @NamedAttributeNode("tags") }))
class Product {

@ManyToMany Set<Tag> tags;

// other properties omitted }

interface ProductRepository extends Repository<Customer, Long> {

@EntityGraph("with-tags") Product findOneById(Long id); }

如您所见,我们利用 Java 8 lambda 和 Querydsl 的类型安全属性引用来定义专用属性 (1) 或给定类型的所有属性 (2) 的绑定。使用 QuerydslBindings.excluding 允许您删除可查询的路径。

Spring Data 示例存储库 中找到一个完整的工作示例,并查看 参考文档 以了解详细信息。

春季数据休息

查询支持

Spring Data Commons(请参阅参考资料)中引入的 Querydsl 支持已集成到 Spring Data REST 中。这意味着您可以通过将简单的属性查询参数附加到请求 URI 来过滤您的集合资源。

在公开星巴克商店位置的 Spring Data REST 示例中,请注意 StoreRepository 现在如何实现 QueryDslPredicateExecutor 以及 QuerydslBinderCustomizer<QStore> 就像上面描述的那样。

Spring Data REST 公开的存储集合资源将允许您发出如下请求:


 @Entity
@NamedEntityGraphs(
  @NamedEntityGraph(name = "with-tags",
    attributeNodes = { @NamedAttributeNode("tags") }))
class Product {

@ManyToMany Set<Tag> tags;

// other properties omitted }

interface ProductRepository extends Repository<Customer, Long> {

@EntityGraph("with-tags") Product findOneById(Long id); }

请注意如何仅返回城市以“York”结尾的商店,正如 StoresRepository QuerydslBinderCustomizer 的实现中所定义的那样。

我们目前正在寻找更明显地宣传此查询机制的选项,例如使用模板变量,甚至提供高级映射工具来自定义要使用的请求参数名称。

自定义 HAL 浏览器

Spring Data REST 的 Gosling 版本附带了一个附加模块,该模块包装了 Mike Kelly 的 HAL 浏览器 ,并通过一些自定义对其进行了调整,以利用我们公开的 API 元数据。要在您的应用程序中使用浏览器,只需将 spring-data-rest-hal-browser 模块添加到您的项目,您的 API 根目录将为浏览器提供接受 text/html 的请求。标准 HAL 响应当然仍然默认提供,或者如果您使用基于 JSON 的 Accept 标头。

虽然 Spring Data REST 模块可以轻松地将浏览器添加到您的应用程序,但它也会对浏览器进行一些微调。当您单击按钮触发非 GET 请求时,浏览器通常会打开一个模式对话框,需要一些原始 JSON 输入。如果您知道自己在做什么,那当然很好,但它有点容易出错而且不太方便,因为您必须了解服务器期望的数据结构。

Spring Data REST 为系统公开的类型公开 JSON 模式文档,利用 profile 文件链接关系,这使得模式通常可以被发现,而无需将发现逻辑绑定到 Spring Data REST 本身。我们提供的浏览器实例将查找该模式元数据,如果它能找到一些元数据,则将其交给 JSON 编辑器,以使用完全从 JSON 模式派生的表单替换默认对话。

查看表单如何允许在模式将其公开为数组时添加行项目。价格和订单日期字段标记为只读,位置字段允许从具有国际化值的枚举中选择值。

可以 在 GitHub 上 找到示例项目。

国际化链接和枚举

正如您在上面的屏幕截图中看到的, restbucks:orders 链接附有人类可读的描述。这些描述是从一个可选的资源包 rest-messages 中提取的,使用 _links.$rel.title 键来定义一个可读的值。该示例使用 rest-messages.properties 作为后备资源包,但还包含 rest-messages_de.properties 以为发送 Accept-Language 标头设置为 de 客户端返回德语标签。

相同的资源包可用于国际化枚举值,以便它们可以以人类可读的方式在客户端上使用。为了不破坏现有的应用程序,这必须通过 RepositoryRestConfiguration.setEnableEnumTranslation(…) 显式激活。可以在 EnumTranslationConfiguration 上配置有关翻译的详细信息。

Spring Data GemFire 和 Apache Geode

对 Pivotal GemFire 8.1 和 Apache Geode 的支持是对 Spring Data GemFire 1.7 最显着的补充。 Pivotal GemFire 已于今年早些时候提交给 Apache 孵化器 ,Spring Data 团队迅速做出响应,将 支持 纳入 Spring Data GemFire。

此外,还添加了其他几个功能来简化使用 Spring 开发 GemFire 和 Apache Geode 应用程序。例如,开发人员现在可以使用注释定义应用程序域对象特定的过期策略:


 @Entity
@NamedEntityGraphs(
  @NamedEntityGraph(name = "with-tags",
    attributeNodes = { @NamedAttributeNode("tags") }))
class Product {

@ManyToMany Set<Tag> tags;

// other properties omitted }

interface ProductRepository extends Repository<Customer, Long> {

@EntityGraph("with-tags") Product findOneById(Long id); }

基于过期的注释支持 SpEL 和 Spring 属性占位符 值。要启用基于注释的过期策略,您只需要在 GemFire 区域上为 TTL 和 TTI 中的一个或两个配置 Spring Data GemFire 的 CustomExpiry 实现 AnnotationBasedExpiration


 @Entity
@NamedEntityGraphs(
  @NamedEntityGraph(name = "with-tags",
    attributeNodes = { @NamedAttributeNode("tags") }))
class Product {

@ManyToMany Set<Tag> tags;

// other properties omitted }

interface ProductRepository extends Repository<Customer, Long> {

@EntityGraph("with-tags") Product findOneById(Long id); }

请参阅参考指南以 了解更多信息 。接下来,通过注释添加了对存储库查询方法 OQL 扩展的支持:


 @Entity
@NamedEntityGraphs(
  @NamedEntityGraph(name = "with-tags",
    attributeNodes = { @NamedAttributeNode("tags") }))
class Product {

@ManyToMany Set<Tag> tags;

// other properties omitted }

interface ProductRepository extends Repository<Customer, Long> {

@EntityGraph("with-tags") Product findOneById(Long id); }

@Trace 启用单独的 OQL 语句调试。 @Limit 限制查询结果集中的结果数量, @Import 使应用程序能够区分名称相似的对象类型。例如,您的应用程序可能同时定义了 org.example.app.core.Customer org.example.app.vendor.xyz.Customer 类型。有关详细信息,请参阅 GemFire 的 文档 @Hint 允许使用 OQL 提示来识别适用于查询的索引。 在此处 了解有关 OQL 扩展的更多信息。

最后,Spring Data GemFire 使用 Spring Data GemFire XML 数据命名空间为 GemFire 缓存和区域快照 提供支持:


 @Entity
@NamedEntityGraphs(
  @NamedEntityGraph(name = "with-tags",
    attributeNodes = { @NamedAttributeNode("tags") }))
class Product {

@ManyToMany Set<Tag> tags;

// other properties omitted }

interface ProductRepository extends Repository<Customer, Long> {

@EntityGraph("with-tags") Product findOneById(Long id); }

您可以 在此处 详细了解 Spring Data GemFire 如何支持导入 ZIP 文件、使用 Spring ApplicationEvents 触发导入和导出快照以及如何适当地过滤导入和导出的数据。

Spring Data 键值和基于地图的存储库

很长一段时间以来,我们一直被要求为 Spring 数据存储库提供一个非常简单的基于 Map 的实现,用于各种目的——主要是测试目的。这些请求最终以与以前略有不同的方式重振 KeyValue 模块

Spring Data KeyValue 现在包含一个基本的基于 Map 的存储库实现,默认情况下将使用 Spring 表达式语言 (SpEL) 查询值,提供排序、分页和基于其集合模块的 Querydsl 集成。它还公开专用 API,以允许键值存储在存储、检索和最重要的查询执行(如果需要)方面利用存储特定优化。

Spring Data KeyValue 存储库使用的默认查询机制基于 SpEL,允许您定义和运行复杂查询。这种方法在 COMPILED 模式 下运行时展示了它的真正威力,因为它有效地编译了要在值上执行的过滤器表达式。或者,您也可以使用 Querydsl 表达式进行类型安全查询。


 @Entity
@NamedEntityGraphs(
  @NamedEntityGraph(name = "with-tags",
    attributeNodes = { @NamedAttributeNode("tags") }))
class Product {

@ManyToMany Set<Tag> tags;

// other properties omitted }

interface ProductRepository extends Repository<Customer, Long> {

@EntityGraph("with-tags") Product findOneById(Long id); }

我们目前为 Ehcache、 Hazelcast Aerospike 扩展了该 API 烹饪,并期待评估选项以集成 Redis 并可能移植一些 Gemfire API 以使用它。

下一步是什么?

接下来是 华盛顿特区的 SpringOne2GX - 我们很高兴在那里见到你 - 与团队取得联系、了解新功能并享受美好时光的最佳场所。与此同时,我们已经在为 Fowler Release Train 准备下一个服务版本,并开始为 Hopper 发布列车开发新功能(嘘……我们将在 SpringOne 的“Spring Data 有什么新功能?”演讲 中先睹为快).


由 Christoph Strobl 撰写的版本。