Hibernate — примеры именованных запросов NamedQuery
В Hibernate существует поддержка именованных запросов, которые называются NamedQueries. Рассмотрим пример использования таких запросов в Hibernate.
Используемые технологии:
Hibernate 5.0.1.Final
Maven 3.2.5
IntelliJ IDEA 14
MySQL 5.6.25
1. Создание именованных запросов NamedQuery в Hibernate
Как понятно из названия именованные запросы — это такие запросы, которые вызываются по имени. К преимуществом такого подхода можно выделить более легкое сопровождение кода, т.к. ваши запросы не выглядят как телега кода с select, insert и т.п. в разных местах, а можно всё сложить в один xml или класс.
Проект полностью использует таблицы и данные из Hibernate – примеры Criteria, поэтому рекомендую сначала глянуть код в этой статье. Приведу данные из заполненной таблицы:
2. Создание запроса в Hibernate с помощью аннотации @NamedQuery (@NamedQueries)
В этом примере я буду вытаскивать данные из таблицы contact, которая приведена выше. Для этого создадим именованный запрос getContactsQuery:
1 2 3 4 5 6 7 8 9 10 11 |
@NamedQueries({ @NamedQuery( name = "getContactsQuery", query = "from ContactEntity ce where ce.id >= :insertId" }) ) @Entity @Table(name = "contact", schema = "", catalog = "javastudy") public class ContactEntity { //остальной код не показан |
Запрос достаточно простой — вывести всё, где id>= переданного значения.
3. Создание именованного запроса в Hibernate с помощью xml
Т.к. в прошлой статье ничего кроме аннотаций не использовалось, то здесь пришлось добавить настройки в xml.
hibernate.cfg.xml:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
<?xml version='1.0' encoding='utf-8'?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property> <property name="connection.url">jdbc:mysql://localhost:3306/javastudy</property> <property name="connection.driver_class">com.mysql.jdbc.Driver</property> <!-- NOTE that after automapping with IDEA property username and password will delete --> <!--and will be: Initial SessionFactory failedorg.hibernate.service.spi.ServiceException: Unable to create requested service--> <property name="connection.username">root</property> <property name="connection.password">admin</property> <!-- NOTE that after automapping with IDEA property username and password will delete --> <mapping class="ru.javastudy.hibernate.dao.ContactEntity"/> <mapping class="ru.javastudy.hibernate.dao.ContactHobbyDetailEntity"/> <mapping class="ru.javastudy.hibernate.dao.ContactTelDetailEntity"/> <mapping class="ru.javastudy.hibernate.dao.HobbyEntity"/> <mapping resource="ContactEntity.hbm.xml"/> <!-- DB schema will be updated if needed --> <!-- <property name="hbm2ddl.auto">update</property> --> </session-factory> </hibernate-configuration> |
И в ту же папку resources добавлен файл ContactEntity.hbm.xml, где создан запрос с именем xmlGetContactsQuery:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<?xml version='1.0' encoding='utf-8'?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="ru.javastudy.hibernate.dao.ContactEntity" table="contact" schema="" catalog="javastudy"> <id name="id" column="id"/> <property name="firstName" column="first_name"/> <property name="lastName" column="last_name"/> <property name="birthDate" column="birth_date"/> <property name="version" column="version"/> </class> <query name="xmlGetContactsQuery"> <![CDATA[from ContactEntity ce where ce.id >= :insertId]]> </query> </hibernate-mapping> |
Замечание — не помещайте запрос выше элемента <class> иначе будет ошибка. Также вы наверное заметили, что запрос обернут в CDATA[], это сделано для того, чтобы при обработке xml не выдавалась ошибка обработки специальных символов вроде < > и т.п..
3. Выполнение запроса
Всё выполняется в одном методе main(). Обратите внимание, что будет работать или вариант с аннотацией или с xml. В противном случае на один из них будет выдаваться ошибка, что запрос с таким именем не найден.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
public static void main(String[] args) { System.out.println("Hibernate tutorial start"); Session session = HibernateSessionFactory.getSessionFactory().openSession(); Transaction tx = session.beginTransaction(); Query query = session.getNamedQuery("getContactsQuery").setString("insertId", "10"); //annotation or xml. Both not working. see hibernate.cfg.xml // Query query = session.getNamedQuery("xmlGetContactsQuery").setString("insertId", "10"); List contactEntity = query.list(); printALL(contactEntity); tx.commit(); session.close(); } private static void printALL(List<Object> contactEntityList) { System.out.println("Print result:"); for(Object contact : contactEntityList) { System.out.println(contact); } } |
Результат будет одинаков:
Print result:
ContactEntity{id=10, firstName=’Name2′, lastName=’LastName2′, birthDate=2014-05-01, version=0}
ContactEntity{id=11, firstName=’Name3′, lastName=’LastName3′, birthDate=2016-09-02, version=0}
ContactEntity{id=12, firstName=’Name4′, lastName=’LastName4′, birthDate=2015-11-01, version=0}
ContactEntity{id=13, firstName=’Name5′, lastName=’LastName5′, birthDate=2012-09-07, version=0}
Исходные коды
*Коды базы данных можете найти в предыдущей статье, указанный в начале статьи
Hibernate NamedQuery — исходный код
46 thoughts on “Hibernate — примеры именованных запросов NamedQuery”
Добавить комментарий
Для отправки комментария вам необходимо авторизоваться.
named query совершенно не для тех целей для чего вы их взялись использовать, а для того чтобы делать средствами SQL сервера, те вещи которые он умеет делать хорошо, чтобы не тащить все данные в коллекцию и не обрабатывать их на стороне ДАО
Статья для тех, кто хочет вообще посмотреть как сделать named query и какие для этого нужны базовые настройки. Соответственно и простенький пример для выборки данных из одной таблицы.
Описывать реально применяемый запрос с десятком связей между таблицами (которые здесь тоже нужно было бы показать), сортировкой и др. в учебной статье мне кажется лишним.
Не работает именные запросы в текущем проекте. Может быть есть какие-то недочёты или что-то не учли?
Скриншоты и результаты из кода статьи, поэтому код рабочий.
Есть парочка вопросов:
1. если в именованном запросе связать две таблицы, и поле id будет повторяться, то hibernate автоматически оставит только уникальные, как этого избежать?
2. в чем разница между schema и catalog?
Спасибо