JPQL 查询:选择一个布尔值,它是对象的两个字段的 AND

Posted

技术标签:

【中文标题】JPQL 查询:选择一个布尔值,它是对象的两个字段的 AND【英文标题】:JPQL query: selecting a single Boolean which is the AND of two of object's fields 【发布时间】:2011-09-26 15:51:18 【问题描述】:

假设我有一个名为 MyData 的 JPA 注释类,它有一个主标识符字段(BigDecimal 类型称为“primaryID”)和两个 Boolean 字段称为“fieldA”和“fieldB”。我想要做的是创建一个 JPA 查询,它将为给定的 MyData 实例选择 fieldA AND fieldB

        final CriteriaBuilder builder = entityManager.getCriteriaBuilder();
        final CriteriaQuery<Boolean> boolQuery = builder.createQuery(Boolean.class);
        final Root<MyData> data = boolQuery.from(MyData.class);
        boolQuery.select(builder.isTrue(builder.and(data.<Boolean> get("fieldA"),
                profile.<Boolean> get("fieldB"))));
        final Predicate primaryIDPredicate = builder.equal(profile.<BigDecimal> get("primaryID"),
                1000);
        boolQuery.where(primaryIDPredicate);

        final TypedQuery<Boolean> myQuery = entityManager.createQuery(boolQuery);

当我的entityManager 执行此查询时,我得到:org.hibernate.hql.ast.QuerySyntaxException: unexpected AST node: and near line 1...。这让我相信我需要一些不同的东西(除了builder.isTrue 方法)来指定我想要一个布尔值和我的对象的两个字段。关于我应该如何构建这个查询的任何想法?

【问题讨论】:

为什么标题说“JPQL”,有问题的时候说需要构造JPA查询? 我理解“JPQL”的意思是“使用 JPA 查询语言”。这是否意味着创建 JPA 字符串查询(参数化与否),或者使用 CriteriaBuilder/CriteriaQuery,我并不特别在意。如果我使用的术语有错误,我会更新问题。 对不起,我自己打错了。在 JPA 中构建查询实际上有两种主要方法:1) JPQL。示例:SELECT a, b FROM C 2) 类型安全的 Criteria Query API。您在示例中使用后者。 仔细查看您的SELECT 表达式。您正在尝试做的是类似 SELECT fieldA = 1 AND fieldB = 1 FROM MyData 的事情,当然,这不是有效的 SQL。您不能在 SELECT 子句中指定谓词。现在想想你试图重现的 SQL 查询,我会尽力帮助你,用 Criteria API 编写它。 嗯,你是对的。看起来您实际上不能将基于布尔的表达式作为 select 子句中的列,至少对于我们正在使用的基础 RDBMS。我刚刚假设这是可能的,因为你总是可以做类似SELECT 1+1 的事情,而且我没有看到布尔值与整数有什么特别之处。无论如何,我只是通过将布尔值作为 where 子句的一部分来让它工作,并检查返回集中是否有超过 0 行。 【参考方案1】:

好的,我最终所做的只是将我想要“与”的布尔值移动到谓词中,然后检查是否返回了任何内容。当然,我可以简单地根据主 ID 检索整个对象 (MyData),并在 Java 代码中完成“与”,但重点是避免获取完整对象,因为它有大量嵌套连接到它引用的集合,对于这种情况,这些是不必要的。

        final CriteriaBuilder builder = entityManager.getCriteriaBuilder();
        final CriteriaQuery<BigInteger> primaryIDQuery = builder.createQuery(BigInteger.class);
        final Root<MyData> data = primaryIDQuery.from(MyData.class);
        primaryIDQuery.select(data.<BigInteger> get("primaryId"));
        final Predicate primaryIDPredicate = builder.equal(profile.<BigInteger> get("primaryId"),1000);
        final Predicate otherPredicate = builder.or(
                builder.isTrue(profile.<Boolean> get("fieldA")),
                builder.isTrue(profile.<Boolean> get("fieldB")));
        primaryIDQuery.where(primaryIDPredicate , otherPredicate);

        final TypedQuery<BigInteger> existenceQuery = entityManager.createQuery(primaryIDQuery);

        boolean whatIWant = existenceQuery.getResultList().size() > 0;

【讨论】:

以上是关于JPQL 查询:选择一个布尔值,它是对象的两个字段的 AND的主要内容,如果未能解决你的问题,请参考以下文章

价值回报方法JPQL的最佳实践

JPA JPQL 怎么判断某个字段是不是为空

在 JPQL 中可以选择 EXISTS() 吗?

JPQL 外键查询

JPA 多对多JPQL查询语句怎么写?

JPQL 构造函数表达式中的 JPQL 和子查询