在jpa标准中,“如果至少有一行返回true”

时间:2013-06-08 04:53:29

标签: java sql database jpa criteria-api

我正在尝试使用JPA(eclipselink)中的条件api创建后续句子, 它很简单,询问某个类别中是否存在某个用户

我想要的句子:

SELECT 
  CASE 
     WHEN EXISTS
          (SELECT * FROM user WHERE category = ?)
     THEN true
     ELSE false
  END 
bind => [10]

我尝试使用此代码:

CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<Boolean> criteriaQuery = criteriaBuilder.createQuery(Boolean.class);
Root<T> root = criteriaQuery.from(tclass);

Subquery<T> subquery = criteriaQuery.subquery(tclass);
Root<T> subroot = subquery.from(tclass);
subquery.select(subroot);

Predicate subPredicate = criteriaBuilder.equal(subroot.get("category"),category);
subquery.where(subPredicate);

Predicate predicateExists = criteriaBuilder.exists(subquery);

Case<Boolean> booleancase = criteriaBuilder.<Boolean>selectCase();
Expression<Boolean> booleanExpression =
    booleancase.when(predicateExists,true)
    .otherwise(false);

criteriaQuery.select(booleanExpression);

TypedQuery<Boolean> typedQuery = entityManager.createQuery(criteriaQuery);
typedQuery.getResultList();

可悲的是我的句子是以下,我想删除最后一个“来自用户”:

SELECT 
  CASE 
      WHEN EXISTS
          (SELECT ? FROM user t1 WHERE (t1.category = ?))  
     THEN ?
     ELSE ? 
  END
FROM user t0    
bind => [1, 110, true, false]

有什么想法吗?

2 个答案:

答案 0 :(得分:1)

不幸的是,JPA不支持在没有实体(表)的情况下选择数据。甚至标准SQL92都不支持这一点 - 看看如何在不同数据库中没有表的情况下进行选择:http://en.wikibooks.org/wiki/SQL_Dialects_Reference/Select_queries/Select_without_tables

在SQL92标准中,您必须在SELECT子句中提供表。

JPA也是一个被广泛接受的标准,并且通常不提供非标准功能,甚至许多标准SQL功能仅出现在最新版本的JPA中(例如,嵌套选择最近才出现在JavaEE 7中的JPA 2.1)。

因此,解决方案是从某个实体中进行选择,该实体在数据库中始终至少有一行,并通过query.setMaxResults(1)将结果限制为最大值1。更好的是创建一个虚拟实体,它总是有1行,其内容永远不会改变。这样可以提高选择的性能。

答案 1 :(得分:0)

最后我解决了:P

TypedQuery<Boolean> typedQuery = 
     entityManager.createQuery(criteriaQuery).setMaxResults(1);

然后句子(不一样,但非常接近):

SELECT 
  CASE 
      WHEN EXISTS
          (SELECT ? FROM user t1 WHERE (t1.category = ?))  
     THEN ?
     ELSE ? 
  END
FROM user t0 LIMIT ?, ? 
bind => [1, 110, true, false,0,1]