Можно ли выбрать 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, я получаю сообщение об ошибке:

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

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

Ответ 1

Этот ответ устарел. Пожалуйста, обратитесь к правильному ответу от Рене Ссылка


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

Обратитесь к документации JPQL BNF от Oracle.

simple_cond_expression :: = сравнение_экспрессия | Между выражением | like_expression | in_expression | null_comparison_expression | empty_collection_comparison_expression | collection_member_expression | exists_expression

exist_expression :: = [NOT] EXISTS (подзапрос)

Ответ 2

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

Начиная с 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();

Ответ 3

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

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

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

Ответ 4

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

Ответ 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

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

Spring-данных JPA

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

или JPA:

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

Ответ 7

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