Spring Data 2020.0 - Spring Data R2DBC 1.2 新特性速览

工程 | Mark Paluch | 2020 年 11 月 18 日 | ...

此版本是 Spring R2DBC 支持的一个重要里程碑。Spring 对 R2DBC 的支持两年前作为实验性项目开始,旨在评估反应式 SQL 集成可能的样子。在此版本中,Spring Data R2DBC 进行了重大重构,将几个组件移入专门的 `spring-r2dbc` 模块,并弃用了 Spring 框架提供的组件。除此之外,Spring Data R2DBC 还带来了以下最值得注意的变更:

  • 通过 `EntityCallback` API 添加生命周期回调
  • 响应式审计
  • `enum` 值和 Postgres Geo 类型的透传

Spring R2DBC

Spring Data R2DBC 现在基于 spring-r2dbc,这是 Spring Framework 中的一个新模块,它提供了核心 R2DBC 支持,例如 DatabaseClientConnectionFactoryInitializerR2dbcTransactionManager。这些组件已被弃用,取而代之的是 Spring R2DBC 组件,并在下一个主要 Spring Data R2DBC 版本中标记为移除。请参阅 迁移指南 了解弃用的内容以及要使用的替代 API。

生命周期实体回调 API

Spring Data Moore 引入了 EntityCallback API,用于在加载、保存和删除操作时预处理和后处理实体。实体回调在持久化操作期间被调用,并允许对实体进行就地修改,如果实体类是不可变的,还可以返回新的对象实例。

EntityCallback 接口支持响应式,它返回 Publisher<T>,其中 T 代表实体类型。返回一个 publisher 允许使用 subscriber context(例如,用于响应式审计)或与执行其他响应式组件集成,这些组件在保存实体之前或加载实体之后执行 I/O 操作。

您可以使用 EntityCallback 来处理各种回调钩子。以下示例定义了一个 BeforeConvertCallback,用于在 Customer 类型的标识符为 null 时,从 H2 序列生成主键值。

@Bean  
BeforeConvertCallback<Customer> idGeneratingCallback(DatabaseClient databaseClient) {  
  
   return (customer, sqlIdentifier) -> {  
  
      if (customer.getId() == null) {  
  
         return databaseClient.sql("SELECT primary_key.nextval") //  
  .map(row -> row.get(0, Long.class)) //  
  .first() //  
  .map(customer::withId);  
      }  
  
      return Mono.just(customer);  
   };  
}

您可以在 R2DBC 实体回调 中阅读更多关于 R2DBC 参考文档 的内容。

枚举值和 Postgres 地理类型直通

Postgres 支持各种数据类型,其中枚举类型和地理类型可以直接从 Spring Data R2DBC 中使用。默认情况下,Spring Data 会将 enum 值转换为 String,使用枚举的 name() 方法来表示枚举值。R2DBC Postgres(自 0.8.4 版本起)支持一个特定的编解码器,该编解码器接受 Java enum 类型,并将它们映射到相应的 Postgres 枚举类型。

考虑以下 Java enum

enum Color {
	Blue, Green, White
}

要在 Postgres 中使用枚举类型,需要先创建它们。

CREATE TYPE color_enum as enum ('Blue', 'Green', `White`);

CREATE TABLE product (id SERIAL PRIMARY KEY, color color_enum);

一旦枚举类型就位,您需要配置驱动程序以将 Java 枚举与相应的 Postgres 枚举类型相关联。这可以通过使用 R2DBC Postgres EnumCodec 构建器来完成。生成的 CodecRegistrar 必须在创建 ConnectionFactory 之前注册到连接配置中。

CodecRegistrar codecRegistrar = EnumCodec.builder().withEnum("color_enum", Color.class).build();

PostgresqlConnectionConfiguration configuration = PostgresqlConnectionConfiguration.builder()
 
    .codecRegistrar(codecRegistrar)
 
    // additional configuration
    .build();

有关 Postgres 枚举类型的更多参考信息,请参阅 驱动程序文档

一旦 ConnectionFactory 配置完成,您就可以配置 Spring Data 中的特定 enum 类型,以便将它们以实际值形式传递给驱动程序,而不是将枚举值转换为 StringR2dbcCustomConversions 是配置简单类型及其转换器的入口点。

R2dbcCustomConversions conversions = R2dbcCustomConversions.of(PostgresDialect.INSTANCE, new ColorConverter());

现在您可以在您的领域类中使用枚举类型了。

class Product {
  @Id Integer id;
  Color color;
  // getter, setter, constructors omitted for brevity
}

有关 使用显式转换器覆盖枚举映射 的信息,请参阅参考文档。

与枚举不同,使用 Postgres 地理类型不需要特殊的设置,因为地理类型具有固定的类型标识符,并映射到单个地理类型。Spring Data R2DBC 支持在您的实体中使用以下特定于驱动程序的类型:

  • io.r2dbc.postgresql.codec.Box
  • io.r2dbc.postgresql.codec.Circle
  • io.r2dbc.postgresql.codec.Line
  • io.r2dbc.postgresql.codec.Lseg
  • io.r2dbc.postgresql.codec.Point
  • io.r2dbc.postgresql.codec.Path
  • io.r2dbc.postgresql.codec.Polygon

或者,您也可以在您的领域模型中使用 Spring Data 的地理类型:

  • org.springframework.data.geo.Box
  • org.springframework.data.geo.Circle
  • org.springframework.data.geo.Point
  • org.springframework.data.geo.Polygon

要使用地理类型,请创建一个表和相应的实体类型。

CREATE TABLE venue (id SERIAL PRIMARY KEY, name VARCHAR(255), location POINT);
class Venue {
  @Id Long id;
  String name;
  Point location;
  // getter, setter, constructors omitted for brevity
}

最后,您可以在应用程序中使用该实体。

R2dbcEntityTemplate template = …;

template.insert(new Venue(null, "Seattle Space Needle", Point.of(47.6204,-122.3491));

获取 Spring 新闻通讯

通过 Spring 新闻通讯保持联系

订阅

领先一步

VMware 提供培训和认证,助您加速进步。

了解更多

获得支持

Tanzu Spring 提供 OpenJDK™、Spring 和 Apache Tomcat® 的支持和二进制文件,只需一份简单的订阅。

了解更多

即将举行的活动

查看 Spring 社区所有即将举行的活动。

查看所有