首页 > 解决方案 > 是否可以避免在 HQL 查询的“where”子句中为布尔函数添加“= true”

问题描述

我正在使用 PostgreSQL 和 JPA/Hibernate。我需要构建一个包含 PostgreSQL 正则表达式比较运算符的 HQL 查询(name ~ 'pattern')。我有以下方言:

public class PostgreSQLExtendedDialect extends PostgreSQL95Dialect {

    public PostgreSQLExtendedDialect() {
        registerFunction("regexp_matches", new SQLFunctionTemplate(BooleanType.INSTANCE, "(?1 ~ ?2)"));
    }

}

但是,以下查询...

entityManager.createQuery("select p from Person p where regexp_matches(p.name, ?1)")
        .setParameter(1, "qwe")
        .getResultList();

...失败,但有以下异常:

antlr.NoViableAltException: unexpected AST node: (
    at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.logicalExpr(HqlSqlBaseWalker.java:2146)
    at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.whereClause(HqlSqlBaseWalker.java:815)
    at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.query(HqlSqlBaseWalker.java:609)
    at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.selectStatement(HqlSqlBaseWalker.java:313)
    at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.statement(HqlSqlBaseWalker.java:261)
    at org.hibernate.hql.internal.ast.QueryTranslatorImpl.analyze(QueryTranslatorImpl.java:271)

同时,以下查询...

entityManager.createQuery("select p from Person p where regexp_matches(p.name, ?1) = true")
        .setParameter(1, "qwe")
        .getResultList();

... 有效,但会产生以下奇怪的 SQL:

where
    person0_.name ~ ?=true

我想知道是否可以避免向已经是布尔表达式的 HQL 部分添加奇怪的“= true”后缀。理想情况下,也许有一些只注册运算符的能力,这样我就可以直接在 HQL 中编写“p.name ~ ?1”。

注意。我知道我可以编写原生查询,但是我有相当复杂的 HQL 查询,这在 SQL 版本中将是一个巨大的巨人,所以我需要保留 HQL。

谢谢!

标签: javahibernatejpa

解决方案


这是不可能的。Mabye 在 Hibernate 6 中,但之前没有办法这样做,因为函数总是应该产生标量值,如果你需要一个谓词,你需要使用一个 JPQL/HQL 谓词。

您可以引入一个自定义SQLFunction实现来呈现 HQL 函数调用regexp_matches(p.name, ?1)regexp_matches(p.name, ?1) and true =以便regexp_matches(p.name, ?1) and true = true在使用regexp_matches(p.name, ?1) = true.

PostgreSQL 可以优化掉重言式true = true


推荐阅读