410013796724260
• Webmoney
R335386147728
Z369087728698
Язык запросов HQLHQL (Hibernate Query Language) – это объекто-ориентированный язык запросов, который очень похож на SQL. Главное различие языков HQL и SQL связано с тем, что SQL формирует запросы из наименований таблиц в базе данных и их столбцов, а HQL работает с сущностями (классами) и их полями (аттрибутами класса). Hibernate транслирует HQL–запросы в понятные для БД SQL–запросы, которые и выполняют необходимые действия в БД. Рассмотрим основные ключевые операторы языка HQL : FROMОператор FROM используется для загрузки (чтения) набора объектов. Пример кода : String hql = "FROM User"; Query query = session.createQuery(hql); List<User> users = query.list(); User представляет POJO класс (User.java), который ассоциирован с таблицей в БД. WHEREОператор WHERE накладывает условие на выборку определенных записей из БД. В следующем коде оператор WHERE используется точно также, как и в обычном SQL :
Query query = session.createQuery("FROM User where name = 'Иван'");
List<User> users = query.list();
Hibernate может использовать оператор WHERE с именованными параметрами (Named Parameters), определяя значение в режиме run-time. Для подстановки соответствующего значения в запрос используется метод setParameter объекта Query, которому в качестве параметров необходимо передать значения :
String hql = "FROM User where name = :paramName";
Query query = session.createQuery(hql);
query.setParameter("paramName", "Alex");
List<User> users = query.list();
Запросы HQL не чувствительны к регистру операторов, за исключением названий Java классов и их свойств. Т.е. 'SeLect' будет эквивалентен 'Select'. Но вот с наименованием сущностей/классов и их полями это не проходит; они должны соответствовать описаниям. INSERTВ HQL поддерживается только форма INSERT INTO ... SELECT ... , которая имеет серьезные ограничения для вставки записей. С точки зрения SQL данная форма позволяет вставить одну или несколько записей в таблицу из запроса SELECT ... . Но это характерно для SQL, а Hibernate (HQL) работает только с сущностями. Попробуем использовать данную форму запроса для вставки записи в Hibernate, и рассмотрим следующий код вставки записи пользователя :
String hql = "insert into User (login, name) " +
"select 'oleg', 'Олег' from User";
int rows = session.createQuery (hql).executeUpdate();
System.out.println("rows : " + rows);
В коде выполняется попытка сохранения сущности User со значениями login='oleg' и name='Олег'. Структуру таблицы и описание сущности можно увидеть в примере связанных сущностей, который описан здесь. Выполнение данного кода выведет в консоль следующую информацию :
Hibernate:
insert into USERS ( id, login, name )
select SEQ_USER.nextval,
'oleg' as col_0_0_,
'Олег' as col_1_0_
from USERS user0_
rows : 2
Hibernate сформировал запрос insert и вставил 2 записи. Если посмотреть содержимое таблицы БД, то там можно будет увидеть новые две записи. Полагаю, что вторая запись лишняя, но как от нее избавиться. Если вместо наименования сущности User в первой или во второй позиции подставить наименование таблицы Users, то Hibernate вызовет QuerySyntaxException :
Exception in thread "main" \
org.hibernate.hql.internal.ast.QuerySyntaxException: \
Users is not mapped [ \
insert into Users(login, name) \
select 'oleg', 'Олег' from net.common.model.User]
Таким образом, можно заключить, что вставку записей в таблицы при использовании HQL лучше выполнять с применением сущностей и стандартных методов save или saveUpdate объекта сессии, как это представлено в примере. UPDATEКлючевое слово UPDATE используется для обновления одного или нескольких полей объекта. При формировании SQL-запроса можно использовать параметры (Named Parameters), рассмотренные выше. Следующий код демонстрирует динамическое определение параметров при обновлении записи. Результат выполнения запроса — количество обновленных (затронутых) записей :
String hql = "update Contact "
+ "SET firstName = :name "
+ ", lastName = :lastName "
+ ", date = :dateParam "
+ " where id = :idParam"
Query query = session.createQuery(hql);
query.setParameter("idParam" , 48);
query.setParameter("name" , "Киса");
query.setParameter("lastName" , "Воробьянинов");
query.setParameter("dateParam", new Date());
int result = query.executeUpdate();
DELETEКлючевое слово DELETE используется для удаления одного или нескольких объектов из таблицы. Пример использования :
String hql = "DELETE User WHERE login = :lg";
Query query = session.createQuery(hql);
query.setParameter("lg", "oleg");
int rows = query.executeUpdate();
Представленный выше код будет выполнен, если сущность User не имеет связанных объектов, т.е. из таблицы БД будет удалена сущность. Но, если к примеру, User имеет один или несколько связанных объектов Autos, как это представлено в примере связанных сущностей, то сервер БД не сможет удалить запись из таблицы Users, поскольку в таблице Autos имеются «ссылочные» записи. В этом случае Hibernate вызовет org.hibernate.exception.ConstraintViolationException : could not execute statement. Для удаления связанных сущностей необходимо использовать объект сессии Session. Следующий код демонстрирует удаление пользователя User, у которого имеются связанные объекты (сущности):
User user = session.load(User.class, 50);
if (user != null) {
session.delete(user);
}
В консоль будут выведены следующие сформированные Hibernate запросы удаления сущности User и связанных с ней сущностей Auto : Hibernate: delete from autos where aid=? Hibernate: delete from autos where aid=? Hibernate: delete from USERS where id=? Обратите внимание, что дочерние/связанные сущности удаляются в первую очередь. Использование алиаса ASОператор AS можно использовать в качестве алиаcа в HQL запросе, особенно, если запрос получается длинным. Следующий код демонстрирует определение алиаса пользователя User как 'u' (без его использования в запросе) : String hql = "FROM User AS u"; Query query = session.createQuery(hql); List results = query.list(); Оператор AS можно не включать в запрос, и сразу же после наименования сущности определить ее алиас : String hql = "FROM User u"; Query query = session.createQuery(hql); List results = query.list(); Ниже представлены примеры кода с использованием алиаса. GROUP BYПри использовании в HQL агрегатных функций необходимо выполнять группировку по определенным в запросе полям, аналогично SQL. Следующий код демонстрирует использование агрегатной функции SUM с группировкой по полю firstName сущности Employee :
String hql = "SELECT SUM (e.salary), e.firtName "
+ "FROM Employee e "
+ "GROUP BY e.firstName";
Query query = session.createQuery(hql);
List results = query.list();
Агрегатные функции HQLВ таблице представлены агрегатные функции, поддерживаемые HQL :
Использование оператора DISTINCT позволяет выделить уникальные значения. Следующий запрос вернет количество уникальных имен сотрудников :
String hql = "SELECT COUNT (distinct e.firstName) "
+ "FROM Employee e";
Query query = session.createQuery(hql);
List results = query.list();
ORDER BYСортировка результатов запроса в HQL выполняется с использованием ORDER BY аналогично SQL. Сортировать значения можно как по возрастанию (ASC ascending), так и по убыванию (DESC descending). Следующий код демонстрирует чтение сотрудников с сортировкой по убыванию :
String hql = "FROM Employee e "
+ "WHERE e.id > 10 ORDER BY e.salary DESC";
Query query = session.createQuery(hql);
List results = query.list();
Если необходимо выполнить сортировку более чем по одному из полей, то можно после оператора ORDER BY указать список полей с порядком сортировки, разделенных запятой :
String hql = "FROM Employee e "
+ "WHERE e.id > 10 "
+ "ORDER BY e.firstName DESC, e.salary DESC";
Query query = session.createQuery(hql);
List results = query.list();
Разбиение на страницыОбъект Query включает два метода, позволяющие организовать разбиение данных по-страницам :
Используя вышеописанные методы можно организовать постраничное представление набора данных. Следующий пример выбирает из БД 8 сотрудников, начиная с 5-ой записи : String hql = "FROM Employee"; Query query = session.createQuery(hql); query.setFirstResult(5); query.setMaxResults (8); List results = query.list(); |
