如何正确判断“存在”JPA Criteria Query子句是返回true还是false?

时间:2011-07-18 05:13:00

标签: java hibernate jpa criteria-api

我不知道如何执行以布尔输出返回的JPA条件查询。

目标是在Oracle上呈现时看起来像这样的条件查询:

select 1 from dual where exists ( ... );

我使用子查询执行的where exists (...)部分。我正在努力解决外部问题。

实际使用此方法是确定exists子句中的子查询是返回true还是false

这就是我写的:

CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();

CriteriaQuery<Object> query = criteriaBuilder.createQuery();
query.from(Boolean.class);
query.select(criteriaBuilder.literal(true));

Subquery<Location> subquery = query.subquery(Location.class);
Root<Location> subRootEntity = subquery.from(Location.class);
subquery.select(subRootEntity);

Path<?> attributePath = subRootEntity.get("State");
Predicate predicate = criteriaBuilder.equal(attributePath, criteriaBuilder.literal("TX"));
subquery.where(predicate);
query.where(criteriaBuilder.exists(subquery));

TypedQuery<Object> typedQuery = em.createQuery(query);


最后一行输出错误,指出“布尔值不是实体”。我认为我的问题是不知道如何表达查询中的“ from ”部分,以便结果输出1或0 / true或false - 而不是实体。

我知道我可以检索任何实体,然后检查结果列表的大小是否为1.

我问如何得到一个布尔结果,既避免了检索这些列的不必要任务,也学习了如何做到这一点。

这可能吗?

谢谢! 爱德华

6 个答案:

答案 0 :(得分:11)

是的,这是可能的。假设您有一个与dual表对应的实体,您将需要在CriteriaQuery#from中使用该实体类。

CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();

CriteriaQuery<Boolean> query = criteriaBuilder.createQuery(Boolean.class);
query.from(dual.class);
query.select(criteriaBuilder.literal(true));

Subquery<Location> subquery = query.subquery(Location.class);
Root<Location> subRootEntity = subquery.from(Location.class);
subquery.select(subRootEntity);

Path<?> attributePath = subRootEntity.get("State");
Predicate predicate = criteriaBuilder.equal(attributePath, criteriaBuilder.literal("TX"));
subquery.where(predicate);
query.where(criteriaBuilder.exists(subquery));

TypedQuery<Boolean> typedQuery = em.createQuery(query);

答案 1 :(得分:7)

您可以为一个属性(例如ID)执行选择,并将返回的最大结果设置为1,以确保数据库不会执行超出必要的工作(如计算所有实例)。然后您的结果列表将为空(exists = false)或具有一个元素(exists = true)。

答案 2 :(得分:3)

Hibernate 5正在运行:

Subquery<Integer> subquery = query.subquery(Integer.class);
Root<Location> subRootEntity = subquery.from(Location.class);
subquery.select(criteriaBuilder.literal(1));

Path<?> attributePath = subRootEntity.get("State");
Predicate predicate = criteriaBuilder.equal(attributePath, criteriaBuilder.literal("TX"));
subquery.where(predicate);
query.where(criteriaBuilder.exists(subquery));

答案 3 :(得分:2)

我知道这是一个较旧的问题,但对于其他任何人来说:如何尝试使用Spring的jpa @Query注释和选择案例查询(取决于您的数据库实现)和返回布尔值的方法。例如(MySQL):

@Query("SELECT CASE WHEN COUNT(l) > 0 THEN TRUE ELSE FALSE END FROM Location l WHERE l.state=?1")
boolean locationForStateExists(String state);

当命名的JPA或查询构建器方法不能完全按照您的意愿执行时,有时只使用@Query中的查询字符串可以节省生命。

答案 4 :(得分:0)

我认为问题是query.from(Boolean.class)。它尝试创建一个“从布尔选择对象”查询。如果你想要一个boolean作为返回类型,你需要使用

CriteriaQuery<Boolean> query = criteriaBuilder.createQuery(Boolean.class)

然后从任何现有实体表中查询以创建有效查询(可能来自子查询的表)。除非你设法映射双表,否则我不认为从双重作品创建。

答案 5 :(得分:-3)

是否所有逻辑都必须在JPA中?如果没有,为什么不使用SELECT COUNT然后使用条件来设置布尔值?

Boolean exists = false;
int count = selectCountQuery();
if (count > 0) {
  exists = true;
}