Возможен ли Select EXISTS () в JPQL?

Я пытаюсь выполнить запрос, который проверяет, если некоторые условия и возвращает простой логический результат на выходе. Что делает его немного сложным, так это то, что одно из условий-проверить, не возвращаются ли результаты для набора критериев.

в настоящее время я использую JPA-2.0 с hibernate в качестве моего провайдера, поддерживаемого MySQL. Я получил пример запроса, работающего нормально в MySQL, но при попытке запустить его в JPQL он проваливается. Запрос MySQL выглядит немного как это:

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

Я также получил тот же вывод, используя CASE, но поскольку JPQL не поддерживает этот оператор.

в любом случае, когда я пытаюсь использовать аналогичный запрос в JPQL, я получаю ошибку:

"неожиданный конец поддерево"

что, насколько я понимаю, означает, что в запросе чего-то не хватает. Кто-нибудь знает, как это исправить?

7 ответов


нет, это невозможно.

относятся к JPQL BNF документация от oracle.

simple_cond_expression ::= comparison_expression | between_expression | like_expression | in_expression | null_comparison_expression | empty_collection_comparison_expression | collection_member_expression | exists_expression

exists_expression :: = [NOT] существует (подзапрос)


вы можете сделать логический запрос, используя case expression.

начиная с JPA 2.0 (Java EE 6) Вы можете создайте 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();

у вас есть несоответствие скобок. Попробуйте удалить один перед not (и те, что вокруг первого существует):

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

вам не нужны скобки exists()


в качестве альтернативы вы можете использовать select count(...) и проверьте, возвращает ли он 0. Это должно быть почти так же эффективно, не требуя писать гораздо больше кода (на самом деле сам запрос, вероятно, будет выглядеть проще).


в проекте, который использует

    <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 в качестве поставщика сохраняемости, я подумал, что могу добавить это здесь.


в проекте с 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=?

это более эффективно для БД, не считая всех записей. Создать собственный запрос

Весна-данные-JPA

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

или JPA:

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