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

使用Blaze Persistence实现List属性包含指定值的查询求助

Blaze Persistence通用查询构建器实现数组包含判断问题

我正在实现一个可跨实体复用的通用查询构建器,基于Blaze Persistence组装查询,核心需求是检查实体的List类型属性(对应PostgreSQL的UUID数组)是否包含指定值,伪代码逻辑为Entity.Attribute.contains(passedValue),但目前所有尝试都无法得到预期结果,细节如下:

实体视图与数据库字段定义

视图中对应字段的Java定义:

@Type(ListArrayType.class)
@Column(name = "co_creators", columnDefinition = "UUID[]")
private List<UUID> coCreators;

该字段由以下SQL生成:

COALESCE(
    (SELECT ARRAY_AGG(cc.cocreatorid)
    FROM cocreator cc
    WHERE cc.elementid = c.id
    AND cc.elementtype = 'COURSE'),
    '{}'
) AS co_creators

已尝试的6种查询方式及问题

1. 直接用值作为条件调用in

代码:

restrictionBuilder = criteria.where(queryParams.getValue().toString());
restrictionBuilder.in(queryParams.getFieldName());

报错:

com.blazebit.persistence.parser.expression.SyntaxErrorException: Could not parse expression '7035bf82-a831-4a78-8615-6cc0e0c1ca26', line 1:4 mismatched input 'bf82' expecting {<EOF>, '+', '-', '*', '/', '%', '||'}

问题原因:Blaze把UUID字符串当成表达式解析,而非字面量,触发语法错误。

2. 使用参数绑定in

代码:

restrictionBuilder = criteria.where(":value");
restrictionBuilder.in(queryParams.getFieldName());
criteria.setParameter("value", queryParams.getValue().toString());

生成的SQL:

SELECT selectedObject FROM CourseView selectedObject WHERE :value IN (:param_0) ORDER BY selectedObject.uuid DESC

问题原因:PostgreSQL中IN操作符不支持数组作为右侧操作数,因此即使值匹配也返回空结果。

3. 使用FUNCTION调用any并绑定参数

代码:

restrictionBuilder = criteria.where("FUNCTION('any', :value, coCreators)");
criteria.setParameter("value", queryParams.getValue().toString());

报错:

Resolved [java.lang.IllegalArgumentException: Parameter name "value" does not exist]

问题原因:Blaze的FUNCTION语法不支持这种命名参数写法,参数无法被正确识别。

4. 直接拼接值到FUNCTION中

代码:

restrictionBuilder =
criteria.where("FUNCTION('any', " + queryParams.getValue().toString() + ", coCreators)");
criteria.setParameter("value", queryParams.getValue().toString());

问题原因:和方式1一致,UUID字符串未被转义为合法字面量,触发语法错误。

5. 转义值后拼接

代码:

restrictionBuilder = criteria.where("FUNCTION('any', '" + queryParams.getValue().toString() + "', coCreators)");

报错:

ExceptionHandlerExceptionResolver : Resolved [com.blazebit.persistence.impl.BuilderChainingException: A builder was not ended properly.]

问题原因:where方法返回的RestrictionBuilder未被正确终止(如未调用eq等收尾方法),破坏了构建链。

6. 转义值并结合eq(true)

代码:

restrictionBuilder =
criteria.where("FUNCTION('any', '" + queryParams.getValue().toString() + "', coCreators)");
restrictionBuilder.eq(true);

报错:

Caused by: org.postgresql.util.PSQLException: ERROR: invalid input syntax for type boolean: "7035bf82-a831-4a78-8615-6cc0e0c1ca26"
  Position: 562

问题原因:PostgreSQL的ANY函数用法错误,正确的布尔判断写法应为= ANY(array),当前写法导致返回值类型不匹配。

求助问题

  1. 能否通过Blaze Persistence实现数组包含值的判断逻辑?
  2. 如果考虑用原生查询条件,如何在Blaze Persistence中将原生条件与其他非原生查询条件结合?

解决方案

方法1:使用Blaze Persistence内置的arraycontains函数(推荐)

Blaze Persistence原生支持PostgreSQL数组操作,直接调用arraycontains即可实现包含判断:

restrictionBuilder = criteria.where("arraycontains(coCreators, :value)");
criteria.setParameter("value", queryParams.getValue()); // 直接传UUID类型,无需转字符串

该写法会生成正确的PostgreSQL SQL:co_creators @> ARRAY[:value]::uuid[],自动处理类型转换和参数绑定。

方法2:正确使用PostgreSQL的= ANY()语法

通过Blaze的表达式解析能力,直接写标准PostgreSQL包含逻辑:

restrictionBuilder = criteria.where(":value = ANY(coCreators)");
criteria.setParameter("value", queryParams.getValue());

Blaze会正确解析表达式并绑定参数,生成的SQL为:value = ANY(selectedObject.co_creators),PostgreSQL会自动处理数组包含判断。

结合原生条件与Blaze构建的条件

如果需要混合原生SQL条件和Blaze构建的条件,可使用RAW方法插入原生片段,同时保留参数绑定能力:

// 原生条件+Blaze标准条件
criteria.where("RAW(':value = ANY(co_creators)', :value)")
       .setParameter("value", queryParams.getValue())
       .andWhere("name LIKE :namePattern")
       .setParameter("namePattern", "%test%");

RAW方法允许插入原生SQL片段,同时支持参数绑定,不会破坏Blaze的查询构建链。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 23:32:03