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的主要内容,如果未能解决你的问题,请参考以下文章