You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Grails中使用Sql executeUpdate预编译语句实现IN查询(含数组参数)的报错解决方法

解决PostgreSQL中预编译语句IN()查询的类型不匹配问题

你遇到的org.postgresql.util.PSQLException: ERROR: operator does not exist: bigint = bigint[]错误,本质是因为PostgreSQL把你传入的long[]数组当成了数据库数组类型,但IN()子句需要的是逗号分隔的单个值列表,不是数组类型,所以数据库找不到对应的匹配操作符。

下面给你几种可行的解决方案,你可以根据自己的代码场景选择:

方案1:手动生成占位符(通用JDBC预编译写法)

这种方法是最通用的,适用于所有JDBC兼容的框架。核心思路是根据数组长度生成对应数量的?占位符,然后把数组元素展开作为参数传入:

long[] test = [1,2]
// 根据数组长度生成多个?占位符,比如数组长度为2就生成"?,?"
def placeholders = test.collect { '?' }.join(',')

// 执行更新操作
sql.executeUpdate(
    "UPDATE outbound_message set acknowledged = true, acknowledged_date = NOW(), acknowledged_from = ? where id in($placeholders) and acknowledged = false",
    // 参数列表:先放用户名,再放数组的所有元素
    [userNameToUse] + test.toList()
)

这样预编译语句会把每个数组元素当成独立的bigint参数,完美匹配id字段的类型,不会再出现类型不匹配的问题。

方案2:利用PostgreSQL的数组操作符= ANY()

PostgreSQL支持直接对数组进行包含查询,你可以用= ANY()替代IN(),同时显式转换参数类型来适配:

long[] test = [1,2]
sql.executeUpdate(
    "UPDATE outbound_message set acknowledged = true, acknowledged_date = NOW(), acknowledged_from = :user where id = ANY(:list::bigint[]) and acknowledged = false",
    [user: userNameToUse, list: test]
)

这里的::bigint[]是PostgreSQL的类型转换语法,把传入的数组参数显式转换成bigint数组类型,数据库就能正确识别并匹配id字段了。这种写法更简洁,不需要手动生成占位符。

方案3:如果用Groovy GORM(Grails项目)

如果你的代码是基于Grails的GORM实现,那么可以直接用GORM的inList方法,它会自动帮你处理预编译和参数绑定:

OutboundMessage.where {
    id inList test
    acknowledged == false
}.updateAll(
    acknowledged: true,
    acknowledgedDate: new Date(),
    acknowledgedFrom: userNameToUse
)

这种写法完全不需要手动写SQL,代码可读性更高,也避免了类型匹配的问题。

内容的提问来源于stack exchange,提问作者Peter

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 01:42:39