如何将元组列表转为OID适配格式传入PostgreSQL IN查询
错误原因
jdbcConvertValue函数处理嵌套列表时,递归返回的是通用Object数组,PostgreSQL JDBC驱动无法直接将其识别为匹配行构造器(customerId, subcustomer)的复合类型数组,因此抛出类型转换异常。
解决方案
方案1:调整类型转换逻辑,生成合规二维数组(推荐)
你需要修改jdbcConvertValue中嵌套列表的处理分支,将List<List<String>>类型的参数转换为PostgreSQL可识别的二维text数组:
fun jdbcConvertValue(session: Session, v: Any?): Any? = when (v) { is Collection<*> -> { when (val firstElem = v.firstOrNull()) { null -> null is String -> session.connection.underlying.createArrayOf("text", v.toTypedArray()) is Long -> session.connection.underlying.createArrayOf("bigint", v.toTypedArray()) is Int -> session.connection.underlying.createArrayOf("bigint", v.toTypedArray()) is UUID -> session.connection.underlying.createArrayOf("uuid", v.toTypedArray()) is List<*> -> { // 适配文本类型二维数组,对应你的customerId、subcustomer均为text字段 val innerFirst = firstElem.firstOrNull() if (innerFirst is String) { val innerArrays = v.map { innerList -> session.connection.underlying.createArrayOf("text", (innerList as List<*>).toTypedArray()) }.toTypedArray() // PostgreSQL中text数组的类型标识为_text session.connection.underlying.createArrayOf("_text", innerArrays) } else { throw Exception("Unsupported nested array element type: ${innerFirst?.javaClass}") } } else -> throw Exception("You need to map your array type $firstElem ${firstElem.javaClass}") } } else -> v }
同时将SQL中的行匹配逻辑改为使用ANY关键字适配数组参数:
where (customerId, subcustomer) = ANY (:customerIdSubCustomerPairs) AND is_deleted = false
方案2:字段拼接匹配(快速应急)
如果不想修改转换逻辑,可以用业务中不会出现的分隔符拼接两个字段,转换为一维数组匹配:
- 参数构造逻辑修改:
"customerIdSubCustomerPairs" to customers.map { "${it["customerId"] as String}|${it["subCustomer"] as String}" }
- SQL条件修改:
where concat(customerId, '|', subcustomer) IN (:customerIdSubCustomerPairs) AND is_deleted = false
注意需确认|不会出现在customerId或subcustomer的业务值中,否则会出现匹配错误。
内容的提问来源于stack exchange,提问作者Leff
相关产品推荐
相关产品推荐

