我不知道如何执行以布尔输出返回的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.
我问如何得到一个布尔结果,既避免了检索这些列的不必要任务,也学习了如何做到这一点。
这可能吗?
谢谢! 爱德华
答案 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;
}