
本文详解如何在 JOOQ 3.14.6+ 中安全、高效地将 List 类型参数用于 UPDATE ... WHERE 条件,重点解决 IN 子句误用 = 导致的 "Type class java.util.ArrayList is not supported" 异常,并提供可直接复用的健壮写法。
本文详解如何在 jooq 3.14.6+ 中安全、高效地将 `list
在 JOOQ 中,field("col").eq(value) 仅支持标量值(如 Long, String, Integer),不支持 List 或 Collection。当你传入 memId = [2, 4, 6] 并调用 .eq(memId) 时,JOOQ 无法将 ArrayList 映射为 PostgreSQL 的合法 SQL 表达式,因此抛出 Type class java.util.ArrayList is not supported in dialect postgres 错误——这并非配置或驱动问题,而是语义错误:SQL 中 = 是标量比较操作符,而多值匹配必须使用 IN。
✅ 正确做法:将 .eq(memId) 替换为 .in(memId)
JOOQ 原生支持 IN 谓词,且能自动适配 PostgreSQL 的 IN (...) 语法,并对空集合、null 等边界情况做安全处理:
public class Request {
private Integer prId;
private List<long> memId;
public Condition applyConditions(Condition condition) {
Condition mod = condition;
if (Objects.nonNull(prId)) {
mod = mod.and(field("send.pr_id").eq(prId));
}
// ✅ 关键修正:使用 .in() 而非 .eq()
if (Objects.nonNull(memId) && !memId.isEmpty()) {
mod = mod.and(field("send.m_id").in(memId));
}
// ⚠️ 注意:若 memId 为空列表([]),.in(emptyList) 会生成 "m_id IN ()" —— 在 PostgreSQL 中语法非法!
// 因此必须显式判空,避免空 IN 子句
return mod; // 修复原代码中的笔误:原为 'modified'
}
}</long>
同时,主方法也建议增强鲁棒性:
public Result> save(Long id, Request req) {
Condition condition = field("send.pr_id").eq(id);
// 避免因 req.memId == null 导致 condition 为 null
condition = req.applyConditions(condition);
// ✅ 使用 .in() + 显式非空校验后,此处可安全执行
return ctx.update(table("send").as("send"))
.set(field("status"), "D")
.where(condition)
.returning()
.fetch();
}
? 重要注意事项:
-
空集合防护:
field("m_id").in(Collections.emptyList())会生成m_id IN (),PostgreSQL 报错ERROR: syntax error at or near ")"。务必在调用.in()前检查!list.isEmpty()。 -
null元素处理:JOOQ 的.in(list)默认忽略null元素(即不生成IS NULL条件)。若业务需匹配m_id IS NULL,需单独追加:mod = mod.or(field("send.m_id").isNull())。 -
性能提示:PostgreSQL 对
IN列表长度无硬限制,但超过数千项时建议改用JOIN或临时表;日常使用( -
类型安全进阶:强烈建议启用 JOOQ 代码生成(官方推荐实践)。生成后的类型安全写法如下:
// 代替字符串字面量,获得编译期检查与 IDE 支持 condition = condition.and(SEND.PR_ID.eq(req.getPrId())); if (req.getMemId() != null && !req.getMemId().isEmpty()) { condition = condition.and(SEND.M_ID.in(req.getMemId())); }
综上,核心原则只有一条:多值匹配永远用 IN,单值匹配才用 =。修正 eq(List) 为 in(List) 并增加空集合防护,即可彻底解决该异常,且保持 SQL 语义清晰、数据库兼容性强。










