JPA и Hibernate-критерии против JPQL или HQL
каковы плюсы и минусы использования критерии или бумага HQL? API критериев-хороший объектно-ориентированный способ выражения запросов в спящем режиме, но иногда запросы критериев сложнее понять / построить, чем HQL.
когда вы используете критерии и когда HQL? Что вы предпочитаете в каких случаях использования? Или это просто вопрос вкуса?
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", определенные в документе сопоставления.
Criteria является объектно-ориентированным API, а HQL означает конкатенацию строк. Это означает, что все преимущества объектно-ориентированности применения:
- при прочих равных условиях версия OO несколько менее подвержена ошибкам. Любая старая строка может быть добавлена в запрос HQL, тогда как только допустимые объекты критериев могут сделать ее деревом критериев. Фактически классы критериев более ограничены.
- С автоматическ-полным, ОО более обнаруживаемо (и таким образом проще в использовании, по крайней мере для меня). Вам не обязательно помнить, какие части запроса идут куда; IDE может помочь вам
- вам также не нужно запоминать особенности синтаксиса (например, какие символы идут куда). Все, что вам нужно знать, как вызывать методы и создавать объекты.
поскольку HQL очень похож на SQL (который большинство разработчиков уже очень хорошо знают), то эти аргументы "не должны помнить" не имеют такого веса. Если HQL был больше по-другому, тогда это было бы более важно.
Я обычно использую критерии, когда я не знаю, какие входные данные будут использоваться для каких фрагментов данных. Как в поисковой форме, где пользователь может ввести любой из 1 до 50 элементов, и я не знаю, что они будут искать. Очень легко просто добавить больше к критериям, когда я прохожу проверку того, что ищет пользователь. Я думаю, что было бы немного более хлопотно поставить запрос HQL в этом обстоятельстве. HQL отлично, хотя, когда я точно знаю, что я хочу.
HQL намного легче читать, легче отлаживать с помощью таких инструментов, как плагин Eclipse Hibernate, и легче регистрировать. Запросы критериев лучше подходят для построения динамических запросов, где большая часть поведения определяется во время выполнения. Если вы не знаете SQL, я мог бы понять, используя запросы критериев, но в целом я предпочитаю HQL, если я знаю, что хочу заранее.
критерии-единственный способ указать естественные поисковые запросы ключей, которые используют специальную оптимизацию в кэше запросов второго уровня. HQL не имеет никакого способа указать необходимую подсказку.
вы можете найти дополнительную информацию здесь:
Criteria Api-одна из хороших концепций Hibernate. по моему мнению, это несколько моментов, с помощью которых мы можем сделать разницу между бумага HQL и Критерии Для API
- HQL должен выполнять как операции выбора, так и операции без выбора данных, но критерии предназначены только для выбора данных, мы не можем выполнять операции без выбора с использованием критериев.
- HQL подходит для выполнения статических запросов, где в качестве критериев подходит для выполнение динамических запросов
- HQL не поддерживает пагинации концепция, но мы можем достигнуть разбиения на страницы с критериями.
- критерии, используемые для выполнения больше времени, чем HQL.
- С критериями мы в безопасности с SQL Injection из-за его динамической генерации запросов, но в HQL, поскольку ваши запросы фиксированы или параметризованы, нет безопасности от SQL Injection
для меня критерии довольно легко понять и сделать динамические запросы. Но недостаток, о котором я говорю до сих пор, заключается в том, что он загружает все отношения много-один etc, потому что у нас есть только три типа FetchModes i.e выберите, прокси и по умолчанию, и во всех этих случаях он загружает много-один (может быть, я ошибаюсь, если так выручить меня:))
2-я проблема с критериями заключается в том, что он загружает полный объект i.e если я хочу просто загрузить 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. то есть. это позволяет проверять время компиляции запроса.
Criteria 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 подходит для выполнения статических запросов, где as критерий подходит для выполнения динамических запросов
- HQL не поддерживает концепцию разбиения на страницы, но мы можем достичь разбиения на страницы с критериями
- критерии, используемые для выполнения больше времени Бумага HQL
- с критериями мы безопасны с SQL-инъекцией из-за ее динамической генерации запросов, но в HQL, поскольку ваши запросы фиксированы или параметризованы, нет безопасности от SQL-инъекции.
критерий запроса для динамически мы можем построить запрос на основе наших входных данных..в случае запроса 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. Вот почему создается JPA. Когда JPQL компилируется, он будет переведен в дерево AST(модель OO) перед переводом на SQL.