В прошлый раз мы узнали, как использовать критерии для выполнения соответствующих операций вместе, но, поскольку критерии не являются методом запроса, официально рекомендованным Hibernate, мы не используем его много. Теперь давайте посмотрим на официально рекомендуемый HQL и узнаем, насколько он мощный.
В чем разница между заявлением запроса HQL или Hibernate и SQL? Разница между одной буквой, ха -ха.
Конечно, это не так. Разница между HQL и SQL заключается в различных идеях. HQL использует объектно-ориентированное направление для запроса, в то время как SQL использует запрос для двухмерных таблиц базы данных. Здесь включено разница в идеях. HQL на самом деле SQL, и он создан Hibernate для преобразования и генерации SQL внутри.
1) Без лишних слов давайте посмотрим на ее силу.
от пользователя
Этот код очень знаком, потому что мы часто используем из имен таблиц в SQL, но разница здесь в том, что пользователь здесь не имя таблицы, а имя класса Entity, а Hibernate помогает нам карту.
Связать операторы SQL, если мы хотим найти определенный атрибут и условно ограничить его в соответствии с определенным атрибутом, мы можем получить аналогичное утверждение:
Выберите usr.name, usr.age от пользователя, где usr.age> 20 и usr.age <60
Таким образом, мы нашли имена и возраст пользователей старше 20 лет и моложе 60 лет. Это легко понять.
И, или, как, <,>, = и т. Д. В операторах SQL можно использовать в HQL.
Следует отметить, что когда мы запросим несколько атрибутов, возвращаемый результат является массивом объекта [], и когда только один, объект возвращается. Это требует различных методов анализа, поэтому вам нужно обратить на это внимание при запросе.
2) Конечно, мы говорили ранее, что HQL ориентирован на объект, и если мы сделаем это, это не объектно-ориентированная идея. Давайте изменим это:
Выберите «Нового пользователя» (USR.Name, USR.Age) из пользователя USR, где USR.Age> 20Таким образом, мы помещаем результат запроса в пользовательский объект. Обратите внимание, что пользовательский конструктор называется здесь. Должен быть пользовательский конструктор, который получает два параметра в классе пользователя, в противном случае будет сообщена ошибка. Сообщение об ошибке примерно следующим образом:
Невозможно найти соответствующий конструктор в классе [org.hibernate.tutorial.domain8.user]
Он не может найти подходящего конструктора. Очень ясно, что просто добавьте конструктор, который получает соответствующие параметры.
Обратите внимание, что когда мы проверили соответствующий идентификатор, мы не узнали. Если в настоящее время мы позвоним в метод SaveorUpdate, он фактически выполнил сохраненную операцию.
Давайте посмотрим на тестовый код:
После выполнения приведенного выше оператора запроса я выполняю следующие операции:
while (iter.hasnext ()) {user user = (user) iter.next (); user.setname ("sun2"); session.saveorupdate (пользователь); } В настоящее время утверждение Hibernate:
Hibernate: вставьте в значения пользователя (user_name, age) (?,?)
Он вставляет новое, а не обновление.
Затем, если нам это нужно для обновления, нам нужно найти идентификатор вместе:
Выберите «Нового пользователя» (USR.Name, USR.Age, USR.ID) из пользователя USR, где USR.Age> (Выберите AVG (USR.Age) из USR)
Не забудьте изменить пользовательский конструктор.
В настоящее время мы снова выполняем наш тестовый код и получите:
Hibernate: обновить пользователь set user_name =?, Age =? где user_id =?
Выберите USR.Name из пользователя USR, где USR.Age> (выберите AVG (usr.age) из USR)
Этот HQL обнаруживает имя пользователя, старше среднего возраста.
4) В Hibernate 3 мы можем легко обновить и удалять объекты, не загружая сначала, а затем удалить в 2. Мы можем сделать это непосредственно в одном операторе:
Обновите имя пользователя name = '123123', где name = 'sun33'
Удалить заявления похожи:
Удалить пользователя, где имя = '123123'
5) Также легко группироваться и сортировать в Hibernate. Просто используйте группу и закажите, и я не буду говорить об этом больше в настоящее время.
6) Мы видим, что приведенное выше написано непосредственно в запрос или обновление. Если нам нужно динамическое назначение или слишком много заданий, мы не можем размирать строки, такие как JDBC. По оценкам, их более 5, и все в команде проекта хотят ругать меня, ха -ха.
Лучше использовать современный метод, вместо этого использовать заполнители, а затем установить конкретные значения.
Наш прямой код:
Query Query = session.createquery («Выберите нового пользователя (usr.name, usr.age, usr.id) из пользователя usr, где usr.name =?»); Query.setString (0, "Shun");
Мы видим, что этот метод похож на подготовленное предприятие, которое мы используем напрямую. Он устанавливается через Set ***, но разница в том, что позиция здесь начинается с 0, в то время как подготовленное предприятие начинается с 1, поэтому обратите на нее особое внимание.
Существует также метод сеанса. Финд в Hibernate2, но так как я сейчас использую 3, я не буду много говорить об этом.
Заполнитель, который мы использовали выше, называется заполнителем заказов, и есть еще один, который называется эталонным заполнителем. Посмотрим:
Query Query = session.createQuery («Выберите нового пользователя (usr.name, usr.age, usr.id) из пользователя usr, где usr.name =: name»); Query.setParameter ("name", "Shun"); Я видел, что в нашем заявлении HQL есть что -то вроде: имя. Это справочный заполнитель. Нам нужно только установить значение через SetParameter позже. Обратите внимание, что первый параметр здесь должен соответствовать значению заполнителя в операторе HQL.
Конечно, некоторые люди могут сказать, что это не объектно-ориентированное, поэтому давайте снова перейдем к объектному ориентированию:
Во -первых, создайте класс, чтобы инкапсулировать значение, которое мы запросите
открытый класс userQuery {private String name; частный int возраст; // Опустите метод get/set} Query Query = session.createquery («Выберите новый пользователь (usr.name, usr.age, usr.id) из пользователя usr, где usr.name =: name"); Userquery uq = new userQuery (); UQ.SetName ("Shun"); Query.SetProperties (UQ); Мы инкапсулируем значения, которые нам нужны, чтобы запросить непосредственно через этот класс. Очень объектно-ориентированный.
У некоторых проектных команд есть некоторые странные правила, которые заявления SQL не разрешают появляться в коде. Если это спецификация, то все коды нашей компании, которую я видел, не имеют квалификации. Много сплайсинга в чашке заставляет его выглядеть подавленным. Действительно трудно поддерживать существующие проекты.
Заявления SQL не допускаются в коде. Это хорошее предложение, но это зависит от случая. Давайте посмотрим, как Hibernate настраивает HQL в картировании файлов.
Посмотрите непосредственно на файл конфигурации:
<Query name = "QueryByName"> <!
Мы добавили такой тег, который указывает, что это оператор HQL.
Когда нам нужно получить это утверждение, нам нужно только добавить предложение в код:
Query Query = session.getNamedQuery ("QueryByName"); Таким образом, оператор HQL получается.
HQL также может быть запрошен с использованием комбинаций в SQL, таких как внутреннее соединение, левое внешнее соединение, правое внешнее соединение, полное соединение.
Давайте посмотрим на их использование:
Давайте сначала посмотрим на класс сущности, что нам нужно использовать в наших тестах:
открытый класс Tuser реализует Serializable {Private Static Long Long SerialVersionUID = 1L; частный INT ID; частный int возраст; Приватное название строки; Private SET <Dards> Addedes = новый хэшсет <drade> (); // Опустить метод get/set} Общественный адрес класса реализует serializable {private static final long serialversionuid = 1l; частный INT ID; частный строковый адрес; частный пользователь Tuser; // Опустить метод get/set} Посмотрим на файл отображения:
<hibernate mapping package = "org.hibernate.tutorial.domain6"> <class name = "tuser" table = "t_user" dynamic-insert = "true" dynamic-update = "true"> <id name = "id" column = "id"> <generator/> </id> <property name = "name =" java.lang. type = "java.lang.integer" colun = "age"/> <set name = "addreses" cascade = "all" table = "t_address" uververse = "true"> <ключ = "user_id"/> <one-many/> </set> </class> </hibernate-mapping> <hibernate-mapping package = "org.hiberte.hiberity.meronte.hiberity.hiberte.hiberity.hiberity.hiberity.hiberity.hiberite.hiberity.hiberite.hiberity. name = "address" table = "t_address" dynamic-insert = "false" dynamic-update = "false" dynamic-update = "false" dynamic-update = "id" type = "java.lang.integer"> <Generator /> < /id> <name = "address =" addrant "usem.lang.lang.sstring" /> <most-to- "user_d_d_don 'use.lang. not null = "true"> </indo-one> </class> </hibernate-mapping>
Вам просто нужно изменить соответствующее имя пакета.
Давайте проведем официальные тесты:
Перед тестированием давайте посмотрим на данные в таблице:
Данные таблицы t_address заключаются в следующем:
Данные таблицы T_USER являются следующими:
1) Во -первых, давайте посмотрим на внутреннее соединение, которое получено в HQL By Inner Join Fetch. Обратите внимание, что значение извлечения здесь состоит в том, чтобы извлечь необходимые данные. Если извлечение не используется, данные, которые мы получили, имеют тип данных объекта [].
Давай посмотрим в первую очередь
от Tuser USR Inner Join quetch usr.addresses
Когда мы запускаем его, мы видим, что выходной выход:
Hibernate: выберите TUSER0_.id AS ID1_0_, Adders1_.id AS ASMER_1_, TUSER0_.Name AS AS name1_0_, tuser0_.age as age1_0_, Adders1_.address as Adders0_, address1_.user_id as user3_0_1_, адреса1_.id as0_. T_ADDRESS ADDRESS1_ ON TUSER0_D = ADDRESS1_.USER_ID
Мы можем увидеть результаты при запуске в MySQL:
Мы видим, что Hibernate превращает его в заявление внутреннего соединения и узнает адрес.
Мы видим, что в результате нет записей Shun4, потому что он не имеет соответствующего адреса и записи.
Когда мы используем внутреннее соединение вместо получения, заявление, которое он печатает:
Hibernate: выберите TUSER0_.id AS ID1_0_, Adders1_.id AS AS AS0_1_, TUSER0_.Name AS AS name1_0_, tuser0_.age as age1_0_, адреса1_.address as address0_, address1_.user_id as user3_0_1_ из T -indress innress quiser innesres tuser0_.id = address1_.user_id
Кажется, что утверждение не отличается, но когда мы его узнаем, он получает объект [] тип массива, поэтому вам необходимо обратить внимание на этот анализ.
Когда мы не используем Fetch, а просто внутреннее соединение, нам нужно проанализировать это так:
Query Query = session.createequery («От Tuser USR Inner присоединиться к USR.Addresses»); Список списка = Query.list (); Iterator iter = list.iterator (); while (iter.hasnext ()) {object [] results = (object []) iter.next (); for (int i = 0; i <results.length; i ++) {System.out.println (результаты [i]); }} Мы видим результат печати:
org.hibernate.tutorial.domain6.tuser@16925b0 org.hibernate.tutorial.domain6.address@914f6a org.hibernate.tutorial.domain6.tuser@787d6a org.hibernate.tutorial.domain6.address@71dc3d org.hibernate.tutorial.domain6.tuser@1326484 org.hibernate.tutorial.domain6.address@16546ef
Каждый из его результатов является соответствующим объектом.
2) Левое внешнее соединение, это эквивалентно левому соединению SQL. Давайте посмотрим на пример напрямую:
от Tuser usr Left Outtere gin ucr.addresses
Когда мы запускаем вышеупомянутое утверждение, Hibernate Отпечатывает:
Hibernate: выберите tuser0_.id as id1_0_, адреса1_.id as as0_1_, tuser0_.name как name1_0_, tuser0_.age as age1_0_, адреса1_.address as address0_, address1_.user_id as user3_0_1_1_.id.id0_. Присоединяйтесь к адресам t_address1_ on tuser0_.id = address1_.user_id
Мы проверили это в MySQL и увидели:
Мы видим, что, хотя Shun4 не имеет соответствующего адреса, он все еще обнаружен. Левое внешнее соединение относится к поиску всех записей в левой таблице.
Я не буду говорить о ситуации без привлечения здесь.
3) Далее давайте посмотрим на правое внешнее соединение. Судя по имени, оно должно быть связано с левым внешним соединением. Мы можем ясно видеть это, посмотрев примеры напрямую.
от Tuser USR Правое Внешнее соединение Fetch USR.Addresses
Мы выполняем его и получаем выход оператора результата из Hibernate:
Hibernate: выберите tuser0_.id как id1_0_, адреса1_.id as as0_1_, tuser0_.name as ance1_0_, tuser0_.age as age1_0_, адреса1_.address as address0_, address1_.user_id as user3_0_1_1_.id0_.ider_.user_id as aser3_0_1_1_1_.id0_. Присоединяйтесь к адресам t_address1_ on tuser0_.id = address1_.user_idМы можем увидеть результаты после выполнения в MySQL:
Здесь мы видим, что адрес test4 и не имеет соответствующего пользователя, соответствующего ему, но он все еще обнаружен. Прямое внешнее соединение относится к поиску всех записей в правильной таблице.
Ситуация извлечения, как и выше. Если вы не понимаете, вы можете взглянуть на внутреннее соединение.