Как правильно определить, существует ли «существующее» предложение JPA Criteria Query, возвращенное true или false? - PullRequest
10 голосов
/ 18 июля 2011

Я не знаю, как выполнить запрос критерия 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);


Последняя строка выдает ошибку, утверждая, что « Boolean не является сущностью ». Я думаю, что моя проблема не в том, как выразить часть запроса « from », чтобы результат выдает 1 или 0 / true или false - не сущность.

Я знаю, что могу извлечь любую сущность, а затем проверить, имеет ли список результатов размер 1.

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

Возможно ли это вообще?

Спасибо! Эдуардо

Ответы [ 6 ]

11 голосов
/ 07 апреля 2013

Да, это возможно.Предполагая, что у вас есть объект, соответствующий вашей таблице 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);
7 голосов
/ 05 апреля 2012

Вы можете сделать выбор для одного свойства (например, идентификатора) и установить максимальный результат, возвращаемый равным 1, чтобы убедиться, что БД не выполняет больше работы, чем необходимо (например, подсчет всех экземпляров).Тогда ваш список результатов будет либо пустым (существует = ложь), либо будет содержать один элемент (существует = истина).

3 голосов
/ 03 мая 2017

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));
2 голосов
/ 16 марта 2016

Я знаю, что это более старый вопрос, но для тех, кто ищет: как насчет попытки использовать аннотацию Spring jpa @Query и запрос select case (в зависимости от вашей реализации db) с методом, который возвращает логическое значение. Например (MySQL):

@Query("SELECT CASE WHEN COUNT(l) > 0 THEN TRUE ELSE FALSE END FROM Location l WHERE l.state=?1")
boolean locationForStateExists(String state);

Иногда простое использование строки запроса в @Query может спасти жизнь, когда именованные методы JPA или построителя запросов не совсем выполняют то, что вам нужно.

0 голосов
/ 17 сентября 2011

Есть ли причина, по которой вся логика должна быть в JPA?Если нет, то почему бы не использовать SELECT COUNT, а затем условие для установки логического значения?

Boolean exists = false;
int count = selectCountQuery();
if (count > 0) {
  exists = true;
}
0 голосов
/ 17 сентября 2011

Я думаю, что проблема в query.from (Boolean.class). Он пытается создать запрос «выбрать объект из логического». Если вы хотите использовать логическое значение в качестве типа возврата, вам нужно использовать

CriteriaQuery<Boolean> query = criteriaBuilder.createQuery(Boolean.class)

Затем выполните запрос из любой существующей таблицы сущностей, чтобы создать действительный запрос (возможно, из таблицы подзапроса). Я не думаю, что создать из двойных работ, за исключением тех случаев, когда вам удалось сопоставить двойную таблицу.

...