#hibernate #hql
#спящий режим #hql
Вопрос:
Например:
EXISTS ( SELECT * FROM [table] WHERE ... )
Как создать такой запрос с помощью Hibernate?
Ответ №1:
HQL не позволяет использовать exists
инструкцию. UPD Начиная с Hibernate 5 он поддерживает его как предикат в WHERE
Вы можете использовать несколько подходов:
- Для Hibrnate 5: вы можете использовать подзапрос с той же таблицей
boolean exists = session.createQuery("select 1 from PersistentEntity where exists (select 1 from PersistentEntity p where ...)").uniqueResult() != null;
. Спасибо автору ниже. count(*) > 0
но это плохо сказывается на производительности Избегайте использования COUNT() в SQL, когда вы могли бы использовать EXISTS()- Используйте
boolean exists = session.createQuery("from PersistentEntity where ...").setMaxResults(1).uniqueResult() != null;
, но это заставит Hibernate загрузить все поля и выполнить гидратацию объекта, даже если вам нужно просто проверить наличие null. - Используйте
session.get(PersistentEntity.class, id) != null
, и это будет работать быстрее, если вы включили кэш второго уровня, но это будет проблемой, если вам нужно больше критериев, чем простоid
. - Вы можете использовать следующий метод:
getSession().createQuery("select 1 from PersistentEntity where ...").uniqueResult() != null)
Комментарии:
1. Сегодня я голосую против, потому что утверждение «HQL не позволяет использовать exists» неверно. docs.jboss.org/hibernate/orm/5.1/userguide/html_single /…
2. Я не уверен, что новое изменение полностью точное. В вопросе конкретно указано «не подзапрос», но новое решение с
exists
использует подзапрос. Я также был бы признателен за комментарий о производительности новогоexists
по сравнению с другими решениями.
Ответ №2:
Если ваша цель — проверить некоторый набор на пустоту, вы можете использовать простой запрос HQL:
boolean exists = (Long) session.createQuery("select count(*) from PersistentEntity where ...").uniqueResult() > 0
Комментарии:
1. не используйте
count(*)
для проверки существования, потому что все агрегированные запросы плохо влияют на производительность blog.jooq.org/2016/09/14 /…
Ответ №3:
Если мы используем предложение WHERE , базе данных, возможно, придется сканировать всю таблицу, чтобы подсчитать записи, соответствующие нашим критериям, но мы можем ограничиться поиском только по одной записи, этого достаточно, чтобы сказать о пустоте.
Если бы не было никаких фильтров поиска, предыдущий запрос был бы допустимым, поскольку база данных выполнила бы некоторую оптимизацию с использованием индекса.
итак, я полагаю, что следующий запрос увеличит производительность по сравнению с предыдущим:
boolean exists = session.createQuery("from PersistentEntity where ...").setMaxResults(1).uniqueResult() != null;
Ответ №4:
Есть несколько приятных комментариев об использовании EXISTS, но нет примеров. Вот мое решение в Hibernate 5.2:
boolean exists = session.createQuery(
"SELECT 1 FROM PersistentEntity WHERE EXISTS (SELECT 1 FROM PersistentEntity p WHERE ...)")
.uniqueResult() != null;
Ответ №5:
Кроме того, если вы используете JpaRepository
, вы можете легко проверить существование объекта через ORM. Вот пример Kotlin:
interface UserRepository : JpaRepository<User, Long> {
fun existsByUsername(username: String): Boolean
}
Ответ №6:
Если вы используете JpaRepository
, это может быть просто, если критерии существования просты, например:
Boolean existsByName(String name);
Если нет, это решение может быть тем, которое вы ищете.
Напишите запрос, который выглядит как:
SELECT CASE WHEN count(attr) > 0 THEN TRUE ELSE FALSE
FROM entity
WHERE <condition>
Пример:
SELECT CASE count(pr_id) > 0 THEN TRUE ELSE FALSE
FROM product
WHERE pr_name LIKE 'a__%'
протестируйте свой запрос, затем добавьте его в свой репозиторий
@Repository
public interface FooRepository extends JpaRepository<FooEntity,UUID>{
@Query(value = "<tested_query_here>", nativeQuery = true)
Boolean existsByConditionYouWrote(<args>);
}
Ответ №7:
Я использовал следующее: SELECT COUNT(e) FROM Entity e
. Отлично работал в Spring Data JPA.
Комментарии:
1. Я получаю
java.lang.ClassCastException: java.lang.Long cannot be cast to java.lang.Boolean
, используя ваш запрос с данными Spring. Не могли бы вы показать полный рабочий пример?
Ответ №8:
Попробуйте:
"select count(e) > 0 from Entity e where..."
Отлично работает с данными Spring.