如何在Spring Data R2DBC中正确映射PostgreSQL数组类型到Kotlin List<>
如何在Spring Data R2DBC中正确映射PostgreSQL数组类型到Kotlin List<>
我完全懂你现在的困扰——静态赋值根本解决不了问题,用ARRAY_TO_STRING又感觉像个临时凑出来的小技巧,还多了不必要的开销。其实Spring Data R2DBC本身就支持PostgreSQL的数组类型映射,咱们直接用原生的方式来搞定,一步到位:
核心思路:用Row的getArray方法读取数组
PostgreSQL的数组类型在R2DBC里是可以直接通过Row对象的getArray方法读取的,咱们只需要把读取到的数组转换成Kotlin的List就行,不需要绕弯子。
1. 映射UUID数组(uuid[])到List<UUID>
对于你查询里的type_ids字段(uuid[]类型),直接用row.getArray指定类型为UUID::class.java,然后转成List即可,同时处理数据库返回空数组{}的情况:
val typeIds = row.getArray("typeIds", UUID::class.java)?.toList() ?: emptyList()
2. 映射字符串数组(varchar[])到List<TimeTypesEnum>
对于time_types字段(varchar[]类型),先读取成String数组,再遍历每个元素用你枚举里的from方法转换,同样处理空数组:
val timeTypes = row.getArray("timeTypes", String::class.java) ?.map { TimeTypesEnum.from(it) } ?: emptyList()
完整的映射代码示例
把这些逻辑放到你原来的map块里,替换掉静态赋值的部分,整个findSmth方法就变成这样:
fun findSmth(): Flux<IncomesDto> { val sql: String = """ -- 你的CTE和查询语句保持不变 SELECT -- 其他字段 type_ids AS "typeIds", time_types AS "timeTypes", -- 其他字段 FROM ${this.tableName} """.trimIndent() return this.databaseClient.sql(sql).map { row, _ -> val typeIds = row.getArray("typeIds", UUID::class.java)?.toList() ?: emptyList() val timeTypes = row.getArray("timeTypes", String::class.java) ?.map { TimeTypesEnum.from(it) } ?: emptyList() IncomesDto( // 其他字段映射 typeIds = typeIds, timeTypes = timeTypes, // 其他字段映射 ) }.all() }
为什么之前会报“Dimensions mismatch”错误?
你之前尝试把数组当成字符串读取时,R2DBC的底层驱动已经识别出这个字段是数组类型,而不是普通字符串,强行按字符串读取就会触发维度不匹配的异常——因为数据库返回的是一维数组,而你试图把它当成0维度的字符串来处理,自然就报错了。
额外注意事项
- 确保你用的是最新版本的
r2dbc-postgresql驱动,旧版本对数组类型的支持可能不够完善; - 你的枚举
from方法已经处理了大小写忽略,所以直接用map转换就没问题,不需要额外处理字符串格式。
这样处理既符合Spring Data R2DBC的设计,又没有额外的SQL转换开销,完全是原生的正确映射方式。
内容来源于stack exchange
相关产品推荐
相关产品推荐

