Spring R2DBC:如何替换已弃用的 DatabaseClient.as(…) 并处理 jsonb 字段的自定义 types/converters
Spring R2DBC: How to replace deprecated DatabaseClient.as(…) and handle custom types/converters for jsonb field
我在迁移到 Spring Boot 2.4 后遇到对象映射问题。到目前为止,我使用的是 Spring Boot 2.3(带有 Kotlin)。
对于示例数据库查询
override fun findMyEntities(searchParams: SearchParams): Flux<MyEntity> =
databaseClient
.sql("SELECT * FROM my_entities ........................... OFFSET :offset LIMIT :limit")
.bind("searchPhrase", searchParams.searchPhrase)
.bind("limit", searchParams.pageSize)
.bind("offset", searchParams.offset)
.map(::mapRow)
.all()
private fun mapRow(row: Row) = MyEntity(
id = row.get("id", UUID::class.java)!!,
name = row.get("name", String::class.java)!!,
description = row.get("description", String::class.java)!!,
creation = row.get("creation", UserActionMetadata::class.java)!!,
)
我遇到错误:
Suppressed: java.lang.IllegalArgumentException: Cannot decode value of type com.mypackage.model.UserActionMetadata
at io.r2dbc.postgresql.codec.DefaultCodecs.decode(DefaultCodecs.java:153)
at io.r2dbc.postgresql.PostgresqlRow.decode(PostgresqlRow.java:90)
at io.r2dbc.postgresql.PostgresqlRow.get(PostgresqlRow.java:77)
at com.mypackage.repository.MyRepotistory.mapRow(MyRepotistory.kt:59)
以上版本升级前的功能是这样的:
.execute("SELECT * FROM ...")
.`as`(MyEntity::class.java)
.fetch()
.all()
发生错误的地方,数据库中的创建字段是JSONB类型。为此,我有自定义读写转换器(在我的配置 class 中扩展了 AbstractR2dbcConfiguration)。
import org.springframework.data.convert.ReadingConverter
import org.springframework.data.convert.WritingConverter
@Configuration
class DatabaseConfig(private val r2dbcProperties: R2dbcProperties, private val objectMapper: ObjectMapper) :
AbstractR2dbcConfiguration() {
@WritingConverter
inner class UserActionMetadataToJsonConverter : Converter<UserActionMetadata, Json> {
override fun convert(source: UserActionMetadata): Json {
return Json.of(objectMapper.writeValueAsString(source))
}
}
@ReadingConverter
inner class JsonToUserActionMetadataConverter : Converter<Json, UserActionMetadata> {
override fun convert(source: Json): UserActionMetadata {
return objectMapper.readValue(source.asString())
}
}
知道如何成功迁移到 Spring Boot 2.4 吗?
我看到了建议 to use R2dbcEntityTemplate, but my queries are too complex, and code will be too bloated. There is also an issue https://github.com/spring-projects/spring-framework/issues/26021。我希望有一些解决方法。
以下代码将数据转换为实体:
import org.springframework.r2dbc.core.DatabaseClient
import org.springframework.data.r2dbc.convert.MappingR2dbcConverter
class MyRepository(
private val databaseClient: DatabaseClient,
private val converter: MappingR2dbcConverter
) {
fun fetchMyEntity() = databaseClient
.sql("...")
.map { row, metadata -> converter.read(MyEntity::class.java, row, metadata) }
.all()
}
我在迁移到 Spring Boot 2.4 后遇到对象映射问题。到目前为止,我使用的是 Spring Boot 2.3(带有 Kotlin)。
对于示例数据库查询
override fun findMyEntities(searchParams: SearchParams): Flux<MyEntity> =
databaseClient
.sql("SELECT * FROM my_entities ........................... OFFSET :offset LIMIT :limit")
.bind("searchPhrase", searchParams.searchPhrase)
.bind("limit", searchParams.pageSize)
.bind("offset", searchParams.offset)
.map(::mapRow)
.all()
private fun mapRow(row: Row) = MyEntity(
id = row.get("id", UUID::class.java)!!,
name = row.get("name", String::class.java)!!,
description = row.get("description", String::class.java)!!,
creation = row.get("creation", UserActionMetadata::class.java)!!,
)
我遇到错误:
Suppressed: java.lang.IllegalArgumentException: Cannot decode value of type com.mypackage.model.UserActionMetadata
at io.r2dbc.postgresql.codec.DefaultCodecs.decode(DefaultCodecs.java:153)
at io.r2dbc.postgresql.PostgresqlRow.decode(PostgresqlRow.java:90)
at io.r2dbc.postgresql.PostgresqlRow.get(PostgresqlRow.java:77)
at com.mypackage.repository.MyRepotistory.mapRow(MyRepotistory.kt:59)
以上版本升级前的功能是这样的:
.execute("SELECT * FROM ...")
.`as`(MyEntity::class.java)
.fetch()
.all()
发生错误的地方,数据库中的创建字段是JSONB类型。为此,我有自定义读写转换器(在我的配置 class 中扩展了 AbstractR2dbcConfiguration)。
import org.springframework.data.convert.ReadingConverter
import org.springframework.data.convert.WritingConverter
@Configuration
class DatabaseConfig(private val r2dbcProperties: R2dbcProperties, private val objectMapper: ObjectMapper) :
AbstractR2dbcConfiguration() {
@WritingConverter
inner class UserActionMetadataToJsonConverter : Converter<UserActionMetadata, Json> {
override fun convert(source: UserActionMetadata): Json {
return Json.of(objectMapper.writeValueAsString(source))
}
}
@ReadingConverter
inner class JsonToUserActionMetadataConverter : Converter<Json, UserActionMetadata> {
override fun convert(source: Json): UserActionMetadata {
return objectMapper.readValue(source.asString())
}
}
知道如何成功迁移到 Spring Boot 2.4 吗?
我看到了建议
以下代码将数据转换为实体:
import org.springframework.r2dbc.core.DatabaseClient
import org.springframework.data.r2dbc.convert.MappingR2dbcConverter
class MyRepository(
private val databaseClient: DatabaseClient,
private val converter: MappingR2dbcConverter
) {
fun fetchMyEntity() = databaseClient
.sql("...")
.map { row, metadata -> converter.read(MyEntity::class.java, row, metadata) }
.all()
}