Quarkus中Hibernate Reactive PostgreSQL的NOT IN子句实现求助
在Quarkus的Hibernate Reactive PostgreSQL环境中实现NOT IN子句的问题
传入参数为java.lang.Number数组,内容:[1, 2],尝试以下三种写法均失败:
尝试的写法及异常
版本1
查询语句:
SELECT count(1) FROM employees WHERE NOT (id = ANY ($1))
异常信息:
io.vertx.pgclient.PgException: ERROR: syntax error at or near "NOT" (42601)
版本2
查询语句:
SELECT count(1) FROM employees WHERE (id NOT IN ANY ($1))
异常信息:
io.vertx.pgclient.PgException: ERROR: syntax error at or near "ANY" (42601)
版本3
查询语句:
SELECT count(1) FROM employees WHERE (id NOT IN ($1))
异常信息:
io.vertx.core.impl.NoStackTraceThrowable: Parameter at position[0] with class = [[Ljava.lang.Number;] and value = [[Ljava.lang.Number;@331e7075] can not be coerced to the expected class = [java.lang.Number] for encoding.
执行查询的Java代码
@Inject PgPool client; // --- client.preparedQuery(queryString).execute(Tuple.tuple(params));
其中queryString为上述查询语句,params为值为[1,2]的Number[]数组。
解决方案
方案1:修正ANY语法并正确绑定数组参数
PostgreSQL中,针对数组的非匹配查询,正确语法为!= ANY,同时需确保参数被识别为PostgreSQL数组类型:
SELECT count(1) FROM employees WHERE id != ANY ($1)
Java代码中,将Number[]转换为对应数据库类型的数组(如Integer[],假设id为整数类型),用PgArray包装后传入:
Integer[] intIds = Arrays.stream(params).map(Number::intValue).toArray(Integer[]::new); client.preparedQuery(queryString).execute(Tuple.of(PgArray.create("integer", intIds)));
方案2:使用unnest函数配合NOT IN
通过unnest将数组转为行数据,适配NOT IN语法:
SELECT count(1) FROM employees WHERE id NOT IN (SELECT unnest($1))
参数绑定方式同方案1,需用PgArray包装数组参数。
方案3:使用Hibernate Reactive Criteria API(推荐)
基于Hibernate Reactive的项目,推荐用Criteria API构建查询,框架会自动处理SQL生成和参数绑定,规避手写SQL的语法与参数问题:
// 假设Employee是实体类,sessionFactory已注入 CriteriaBuilder cb = sessionFactory.getCriteriaBuilder(); CriteriaQuery<Long> countQuery = cb.createQuery(Long.class); Root<Employee> root = countQuery.from(Employee.class); List<Number> excludeIds = Arrays.asList(params); countQuery.select(cb.count(root)) .where(cb.not(root.get("id").in(excludeIds))); Long result = session.createQuery(countQuery).getSingleResult();
内容的提问来源于stack exchange,提问作者Amaresh Kulkarni
相关产品推荐
相关产品推荐

