Spring R2DBC DatabaseClient.as(…)

Posted

技术标签:

【中文标题】Spring R2DBC DatabaseClient.as(…)【英文标题】: 【发布时间】:2021-02-15 05:29:54 【问题描述】:

在我的 spring-boot 2.3 应用程序中,我有一个使用 DatabaseClient 的简单数据方法:

fun getCurrentTime(): Mono<LocalDateTime> =
    databaseClient
        .execute("SELECT NOW()")
        .asType<LocalDateTime>()
        .fetch()
        .first()

使用 spring-boot 2.4(以及 spring 5.3 和 spring-data-r2dbc 1.2),不推荐使用 spring-data-r2dbc 中的 org.springframework.data.r2dbc.core.DatabaseClient,取而代之的是 spring-r2dbc 的 org.springframework.r2dbc.core.DatabaseClient - 它具有不同的 API。

调整非常简单 - 除了 kotlin 扩展 asType,它不是新 DatabaseClientExtensions 的一部分。

fun getCurrentTime(): Mono<LocalDateTime> =
    databaseClient
        .sql("SELECT NOW()")
        .map  row: Row ->
            row.get(0, LocalDateTime::class.java)!!
        
        .one()

这些扩展是否在其他地方,或者我如何使用具体类型参数进行转换?

【问题讨论】:

【参考方案1】:

TL;DR

迁移到 Spring R2DBC 后没有as(Class) API。

一点背景

DatabaseClient 在实验性的 Spring Data R2DBC 项目中开始了它的旅程,尝试了各种方法。其中一位评估了文本 SQL API 和对象映射 API 可以结合在一起的紧密程度。 Spring Data中的DatabaseClient暴露了select().from("table").as(targetType)等各种API方法。

事实证明,此功能很有用,但存在一定的局限性,因为 API 越深入实体甚至面向聚合的方向,实际 API 变得越复杂,并且在某些时候,简单对象映射和实体之间的界限(例如,实体生命周期回调)模糊。

我们决定引入R2dbcEntityTemplate 作为所有实体绑定操作的抽象,以支持最常见的用例。看看之前的 Fluent API,对于所有需要即席 SQL 查询、聚合、函数调用等的用例来说,仍然存在差距。

与此同时,该项目被证明是有用的,我们已经确定了可以迁移到 Spring Framework 5.3 中的核心支持类,因此 Spring Data R2DBC 1.2 可以基于 Spring R2DBC。

在迁移代码时,我们无法找到合适的方法。公平地说,DatabaseClient 提供与NamedParameterJdbcTemplate 几乎相同的抽象级别(存储过程除外)。 Spring JDBC 清楚地附带了几个 RowMapper 实现,例如 SingleColumnRowMapperDataClassRowMapper,它们对 Spring R2DBC 也很有用。

最后的想法

从用户的角度来看,as(…) 看到了很多需求,我们应该调查一下,这个功能(或它的变体)是如何出现的。

【讨论】:

感谢您的见解!提到 R2dbcEntityTemplate 很有帮助,我将在存储库不足的情况下使用它,例如用于专门的 JOIN 查询。 FWIW,我在 Spring Framework 中提交了一张票:github.com/spring-projects/spring-framework/issues/26021

以上是关于Spring R2DBC DatabaseClient.as(…)的主要内容,如果未能解决你的问题,请参考以下文章

Spring Data R2DBC响应式操作MySQL

MYSQL R2DBC 的 Spring Data 多主机设置

如何在 R2DBC 和 Spring WebFlux 中加入多个表?

Spring数据r2dbc和分页

Spring Data R2DBC 响应式数据库操作使用

Spring R2DBC DatabaseClient.as(…)