Можно ли выбрать 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=?