【问题标题】:Is Select EXISTS() possible in JPQL?在 JPQL 中可以选择 EXISTS() 吗?
【发布时间】:2011-10-11 20:33:21
【问题描述】:

我正在尝试运行一个查询来检查某些条件是否为真,并返回一个简单的布尔结果作为输出。有点棘手的是,其中一个条件是测试一组条件是否没有返回结果。

我目前使用 JPA-2.0 和 hibernate 作为我的提供程序,由 MySQL 提供支持。我得到了一个在 MySQL 中运行良好的示例查询,但是当试图让它在 JPQL 中运行时它失败了。 MySQL 查询看起来有点像这样:

Select exists(Select statement with criteria) 
  or not exists(Select statement with criteria);

我也使用 CASE 得到了相同的输出,但 JPQL 不支持该语句。

无论如何,当我尝试在 JPQL 中使用类似的查询时,我得到了错误:

“子树的意外结束”

据我了解,这意味着查询中缺少某些内容。有谁知道如何解决它?

【问题讨论】:

    标签: jakarta-ee jpa jpa-2.0 jpql


    【解决方案1】:

    您的括号不匹配。尝试删除not 之前的那个(并且第一个周围的存在):

    select exists(Select statement with criteria) 
      or not exists(Select statement with criteria);
    

    exists() 周围不需要括号

    【讨论】:

    【解决方案2】:

    这个答案已经过时了。请参考Rene Link的正确答案


    不,这是不可能的。

    请参阅 oracle 的 JPQL BNF 文档。

    simple_cond_expression ::= 比较表达式 |之间的表达式 |像表达式 | in_表达式 | null_comparison_expression | empty_collection_comparison_expression |集合成员表达式 | exists_expression

    exists_expression ::= [NOT] EXISTS(子查询)

    【讨论】:

      【解决方案3】:

      或者,您可以使用select count(...) 并测试它是否返回0。这应该几乎同样有效,无需编写更多代码(事实上,查询本身可能看起来更简单)。

      【讨论】:

      • 不一定。 exists(...) 可能会在找到第一个结果后存在。 count(...) 将不得不扫描更多的索引/表行以确定实际计数。
      • @KonradGarus:不过,这并不重要,count(..) 是唯一适用于 JPQL 的解决方案。所以,当生活给你柠檬时......
      【解决方案4】:

      您可以使用case expression 进行布尔查询。

      从 JPA 2.0 (Java EE 6) 开始,您可以 create a TypedQuery 。

      String query = "select case when (count(*) > 0)  then true else false end from ......"
      TypedQuery<Boolean> booleanQuery = entityManager.createQuery(query, Boolean.class);
      boolean exists = booleanQuery.getSingleResult();
      

      在 JPA 1.0 (Java EE 5) 中,您必须使用无类型查询。

      Query booleanQuery = entityManager.createQuery(query);
      boolean exists = (Boolean) booleanQuery.getSingleResult();
      

      【讨论】:

      • 更易读的方式是:"select (count(*) > 0) from ..."
      • @Reda 这仍然会搜索整个索引/表,尽管数据库可以并且应该在找到第一个结果后停止。
      • @T3rm1 是的,你是对的,但不幸的是我不知道是否有其他解决方案
      【解决方案5】:

      在一个项目中使用

          <dependency>
              <groupId>org.hibernate</groupId>
              <artifactId>hibernate-core</artifactId>
              <version>4.2.4.Final</version>
          </dependency>
          ...
      

      我成功使用了一个

      exists(select s.primaryKey from Something s)
      

      条款。所以它可能已经改变了。它也可能是 Hibernate 专有的。由于很多人使用 Hibernate 作为持久性提供程序,我想我可以在这里添加它。

      【讨论】:

        【解决方案6】:

        在一个使用 Hibernate 5.2(支持 JPA 2.1)和 Spring Data Jpa 2.0.6 的项目中,我成功地使用了这个 JPQL 查询:

        @Query("SELECT COUNT(c) > 0 FROM Contract c WHERE c.person.id = :pid")
        Boolean existContractForPerson(@Param("pid") Long personId);
        

        在日志中,我读到生成的本机查询如下:

        select count(contract0_.contract_id)>0 as col_0_0_ from contracts contract0_ where contract0_.fk_person_id=?
        

        【讨论】:

        【解决方案7】:

        DB 不计算所有记录更有效。创建原生查询

        Spring-Data-JPA

        @Query(value = ".....", nativeQuery = true)
        

        或 JPA:

        @NamedNativeQuery(name=.., query="..", resultClass=..)
        

        【讨论】:

        • 你在用理论效率换取潜在的代码破坏,因为本机查询语法要到运行时才会验证。
        猜你喜欢
        • 2011-02-15
        • 2017-06-13
        • 2011-08-16
        • 2010-12-11
        • 2021-08-19
        • 1970-01-01
        • 2011-01-17
        • 2010-11-15
        • 1970-01-01
        相关资源
        最近更新 更多