Java 在少年警讯的准则中,";如果至少有一行返回true“;

Java 在少年警讯的准则中,";如果至少有一行返回true“;,java,sql,database,jpa,criteria-api,Java,Sql,Database,Jpa,Criteria Api,我试图使用JPA(eclipselink)中的CriteriaAPI创建以下句子, 询问某个类别中是否存在某个用户很简单 我想要的句子是: SELECT CASE WHEN EXISTS (SELECT * FROM user WHERE category = ?) THEN true ELSE false END bind => [10] 我正在尝试使用以下代码: CriteriaBuilder criteriaBuild

我试图使用JPA(eclipselink)中的CriteriaAPI创建以下句子, 询问某个类别中是否存在某个用户很简单

我想要的句子是:

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();

有什么想法吗?

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

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

JPA也是一个被广泛接受的标准,通常不提供非标准特性,甚至许多标准SQL特性也只出现在最新版本的JPA中(例如,最近JavaEE7中的JPA2.1才出现嵌套选择)


因此,解决方案是从某个实体中进行选择,该实体在数据库中始终至少有一行,并通过query.setMaxResults(1)将结果限制为max 1。更好的方法是创建一个虚拟实体,它始终有一行,并且其内容从未更改。这将提高select的性能。

最后我解决了:p

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

如果在subPredicate中使用subroot而不是root,会发生什么?对不起,它是subPredicate中的subroot。我在stackoverflow中写错了(我已经纠正了这个问题)。谢谢,但这并不能解决我的问题:如果你已经有了简单明了的SQL查询,你为什么想要这个复杂且不可读的java代码?因为我可以通过编程编辑句子,更改表,更改列,而不编辑任何字符串(字符串的版本容易出错)
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]