JPQL 是否支持在另一个表达式中使用布尔结果?

Does JPQL support the use of a boolean result in another expression?

我正在尝试编写一个查询来支持搜索 API。专门针对标志 searchDrafts - 如果标志是 true 我必须获得带有 status DRAFT 的行,否则我必须获得所有具有任何 [=15= 的行] 除了 DRAFT.

在常规 SQL 中,以下查询工作正常:

SELECT id, status
FROM records
where ((status = 'DRAFT') = :searchDrafts);

但是,JPQL 中的类似功能不起作用:

SELECT r 
FROM Records r 
WHERE ((r.status = 'DRAFT') = :searchDrafts);

它给出错误:

unexpected AST node: = near line 1, column nn

在 JPQL 中有什么方法可以在另一个表达式中使用布尔结果的值吗?

另一种方法是用更长的时间来做,但有点冗长。这在 JPQL 中工作正常:

SELECT id, status
FROM records
where (:searchDrafts=true AND (status = 'DRAFT')) 
or (:searchDrafts=false AND (status != 'DRAFT'));

Jakarta Persistence 3.0 规范中的 JPQL 语法不允许这样做。 (我手头有3.0,但我不希望早期的有所不同。)布尔比较对应于这个产生式规则:

comparison_expression ::=
    ...
    boolean_expression {= | <>} {boolean_expression | all_or_any_expression} |
    ...

那么 comparison_expression 只会作为 conditional_expression 生产规则的一部分遇到:

conditional_expression ::= conditional_term | conditional_expression OR conditional_term
conditional_term ::= conditional_factor | conditional_term AND conditional_factor
conditional_factor ::= [NOT] conditional_primary
conditional_primary ::= simple_cond_expression | (conditional_expression)
simple_cond_expression ::=
    comparison_expression |
    ...

conditional_expression 是直接在 WHENWHEREHAVINGON 子句中的内容。这意味着 comparison_expression 不能是 boolean_expression.

除了您使用 AND 的解决方案外,这个似乎也有效:

SELECT r 
FROM Records r 
WHERE CASE WHEN r.status = 'DRAFT' THEN TRUE ELSE FALSE END = :searchDrafts;

它很丑陋,但它确实将 conditional_expression 转换为 boolean_expression

实际上,您最好有两种不同的查询:一种针对“=”,另一种针对“<>”。

总的来说,感觉像是JPA标准中的遗漏。