JPA и Hibernate-критерии против JPQL или HQL


каковы плюсы и минусы использования критерии или HQL? API критериев-это хороший объектно-ориентированный способ выражения запросов в спящем режиме, но иногда запросы критериев сложнее понять/построить, чем HQL.

когда вы используете критерии и когда HQL? Что вы предпочитаете в каких случаях использования? Или это просто дело вкуса?

21 278

21 ответ:

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

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

существует разница в производительности между HQL и criteriaQuery, каждый раз, когда вы запускаете запрос с помощью criteriaQuery, он создает новый псевдоним для имени таблицы, который не отражается в последнем запрошенном кэше для любой БД. Это приводит к накладным расходам на компиляцию сгенерированного SQL, что занимает больше времени для выполнения.

относительно выбора стратегий [http://www.hibernate.org/315.html]

  • критерии уважает лень настройки в ваших сопоставлениях и гарантирует, что то, что вы хотите загрузить загружается. Это означает, что один запрос критериев может привести к нескольким операторам SQL immediate SELECT для извлечения подграфа со всеми не ленивыми сопоставленными ассоциациями и коллекциями. Если вы хотите изменить " как "и даже" что", используйте setFetchMode (), чтобы включить или отключить извлечение внешнего соединения для определенной коллекции или ассоциации. Запросы критериев также полностью учитывают стратегию выборки (join vs select vs подзапрос выборки.)
  • HQL уважает настройки лени в ваших сопоставлениях и гарантирует, что то, что вы хотите загрузить, будет загружено. Это означает, что один запрос HQL может привести к нескольким операторам SQL immediate SELECT для извлечения подграфа со всеми не ленивыми сопоставленными ассоциациями и коллекциями. Если вы хотите изменить " как "и даже "что", используйте LEFT JOIN FETCH, чтобы включить извлечение внешнего соединения для определенной коллекции или nullable many-to-one или one-to-one association, или JOIN FETCH, чтобы включить внутренняя выборка соединения для ненулевой ассоциации "многие к одному" или "один к одному". Запросы HQL не учитывают fetch= "join", определенные в документе сопоставления.

критерии-это объектно-ориентированный API, в то время как HQL означает конкатенацию строк. Это означает, что все преимущества объектно-ориентированности применения:

  1. при прочих равных условиях версия OO несколько менее подвержена ошибкам. Любая старая строка может быть добавлена в запрос HQL, тогда как только допустимые объекты критериев могут сделать ее деревом критериев. Фактически, классы критериев более ограничены.
  2. с автозаполнением, OO является более обнаружимым (и, таким образом проще в использовании, по крайней мере для меня). Вам не обязательно помнить, какие части запроса идут куда; IDE может помочь вам
  3. вам также не нужно запоминать детали синтаксиса (например, какие символы идут куда). Все, что вам нужно знать, как вызывать методы и создавать объекты.

поскольку HQL очень похож на SQL (который большинство разработчиков уже очень хорошо знают), то эти аргументы "не нужно помнить" не имеют такого большого веса. Если бы HQL было больше по-другому, тогда это было бы более importatnt.

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

HQL намного легче читать, легче отлаживать с помощью таких инструментов, как плагин Eclipse Hibernate, и проще регистрировать. Запросы критериев лучше подходят для построения динамических запросов, где большая часть поведения определяется во время выполнения. Если вы не знаете SQL, я мог бы понять, используя запросы критериев, но в целом я предпочитаю HQL, если я знаю, что я хочу заранее.

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

вы можете найти дополнительную информацию здесь:

критерии Api является одним из хорошей концепции Hibernate. по моему мнению, это те немногие точки, с помощью которых мы можем сделать разницу между HQL и Критерии Api

  1. HQL должен выполнять как операции выбора, так и операции без выбора данных, но критерии предназначены только для выбора данных, мы не можем выполнять операции без выбора с использованием критериев.
  2. HQL подходит для выполнения статических запросов, где в качестве критериев подходит для выполнение динамических запросов
  3. HQL не поддерживает разбиение на страницы концепция, но мы можем достичь разбиения на страницы с критериями.
  4. критерии, используемые для выполнения больше времени, чем HQL.
  5. С критериями мы в безопасности с SQL Injection из-за его динамической генерации запросов, но в HQL, поскольку ваши запросы либо фиксированы, либо параметризованы, нет безопасности от SQL-инъекции

для меня критерии довольно легко понять и сделать динамические запросы. Но недостаток, который я говорю до сих пор, заключается в том, что он загружает все отношения много-один и т. д., Потому что у нас есть только три типа FetchModes, т. е. Select, Proxy и Default, и во всех этих случаях он загружает много-один (может быть, я ошибаюсь, если так мне поможет :))

2-я проблема с критериями заключается в том, что он загружает полный объект, т. е. если я хочу просто загрузить EmpName сотрудника, он не придумает это insted, он придумает полный Объект Employee и я могу получить от него EmpName из-за этого это действительно плохо работает в отчетности. где, поскольку HQL просто загружает (не загружал ассоциацию / отношения), что вы хотите, чтобы увеличить производительность во много раз.

одной из особенностей критериев является то, что он будет безопасен u от SQL-инъекции из-за его динамической генерации запросов, где, как и в HQL, запросы ur либо фиксированы, либо параметризованы, поэтому не безопасны от SQL-инъекции.

также, если вы пишете HQL в UR aspx.cs файлы, тогда вы тесно связаны с УР Далом.

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

чтобы использовать лучшее из обоих миров, выразительность и лаконичность HQL и динамический характер критериев считают использование Querydsl.

Querydsl поддерживает JPA / Hibernate, JDO, SQL и коллекции.

Я являюсь сопровождающим Querydsl, поэтому этот ответ является предвзятым.

для меня самый большой выигрыш по критериям-это пример API, где вы можете передать объект и hibernate построит запрос на основе этих свойств объекта.

кроме того, API критериев имеет свои причуды (я считаю, что команда hibernate перерабатывает api), например:

  • критерии.createAlias ("obj") заставляет внутреннее соединение вместо возможного внешнего соединения
  • вы не можете создать один и тот же псевдоним два раза
  • некоторые предложения sql не имеют простой критерии соответствия (например, подвыборка)
  • etc.

Я обычно использую HQL, когда мне нужны запросы, подобные sql (удалить из пользователей, где status='blocked'), и я обычно использую критерии, когда я не хочу использовать добавление строк.

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

критерии api обеспечивают одну отличную функцию, которую не предоставляет ни SQL, ни HQL. то есть. это позволяет проверить время компиляции запроса.

критерии API лучше подходит для динамически генерируемых запросов, когда фильтры запросов динамически применяются во время выполнения. Поэтому, чтобы предотвращение атак SQL-инъекций при построении динамических запросов, критерии API является очень хорошим выбором.

критерии запросов менее выразительны, и вы можете легко в конечном итоге с очень сложным и неэффективным SQL сгенерированный запрос. Однажды я присоединился к большому корпоративному приложению, где API критериев был по умолчанию метод запроса и даже не обширный обзор кода могли бы преодолеть ужас не зная, какие SQL-запросы мы собирались в конечном итоге.

JPQL или HQL гораздо более выразительны, и гораздо проще предсказать связанный сгенерированный SQL-запрос. Кроме того, гораздо проще просматривать свои запросы HQL, чем критерии.

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

стоит отметить, что выбор объектов с JPQL или критериями API имеет смысл, если вам нужно их изменить. В противном случае проекция DTO работает лучше. Проверьте в этой статье для получения дополнительной информации.

мы использовали в основном критерии в нашем приложении в начале, но после того, как он был заменен на HQL из-за проблем с производительностью.
В основном мы используем очень сложные запросы с несколькими соединениями, что приводит к нескольким запросам в критериях, но очень оптимизировано в HQL.
Дело в том, что мы используем только несколько свойств на конкретном объекте, а не на полных объектах. С критериями проблема также заключалась в конкатенации строк.
Пусть говорят, Если вам нужно отобразить имя и фамилию пользователь в HQL это довольно легко (name || ' ' || surname) но в Crteria это невозможно.
Для преодоления этого мы использовали ResultTransormers, где были методы, где такая конкатенация была реализована для необходимого результата.
Сегодня мы в основном используем HQL следующим образом:

String hql = "select " +
            "c.uuid as uuid," +
            "c.name as name," +
            "c.objective as objective," +
            "c.startDate as startDate," +
            "c.endDate as endDate," +
            "c.description as description," +
            "s.status as status," +
            "t.type as type " +
            "from " + Campaign.class.getName() + " c " +
            "left join c.type t " +
            "left join c.status s";

Query query =  hibernateTemplate.getSessionFactory().getCurrentSession().getSession(EntityMode.MAP).createQuery(hql);
query.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
return query.list();

таким образом, в нашем случае возвращаемые записи являются картами необходимых свойств.

  • HQL должен выполнять как операции выбора, так и операции без выбора данных, но критерии предназначены только для выбора данных, мы не можем выполнять операции без выбора с использованием критериев
  • HQL подходит для выполнения статических запросов, где в качестве критерия подходит для выполнения динамических запросов
  • HQL не поддерживает концепцию разбиения на страницы, но мы можем достичь разбиения на страницы с критериями
  • критерии, используемые для выполнения больше времени, то HQL
  • с критериями мы безопасны с SQL-инъекцией из-за ее динамической генерации запросов, но в HQL, поскольку ваши запросы либо фиксированы, либо параметризованы, нет безопасности от SQL-инъекции.

источник

критерии запроса для динамически мы можем построить запрос на основе наших inputs..In случай запроса Hql-это статический запрос после того, как мы построим, мы не можем изменить структуру запроса.

Я не хочу пинать мертвую лошадь здесь, но важно отметить, что запросы критериев теперь устарели. Используйте HQL.

Я также предпочитаю критерии запросов для динамических запросов. Но я предпочитаю hql для запросов на удаление, например, если удалить все записи из дочерней таблицы для родительского идентификатора "xyz", это легко достигается HQL, но для API критериев сначала мы должны запустить N количество запросов на удаление, где n-количество записей дочерней таблицы.

большинство ответов здесь вводят в заблуждение и упоминают, что Criteria Queries медленнее, чем HQL, что на самом деле не так.

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

а также с Критерии Запроса вы получаете объектно-ориентированное управление которого там нет с HQL.

для получения более подробной информации ответ здесь.

есть и другой способ. Я закончил с созданием парсера HQL на основе исходного синтаксиса hibernate, поэтому он сначала анализирует HQL, а затем может динамически вводить динамические параметры или автоматически добавлять некоторые общие фильтры для запросов HQL. Он отлично работает!

этот пост довольно старый. Большинство ответов говорят о критериях гибернации, а не о критериях JPA. JPA 2.1 добавил CriteriaDelete/CriteriaUpdate и EntityGraph, который контролирует, что именно нужно извлечь. Критерии API лучше, так как Java-это OO. Именно поэтому созданные ассоциации. Когда JPQL компилируется, он будет переведен в дерево AST(OO model) перед переводом на SQL.

HQL может вызвать безопасность проблемы, как SQL инъекции.