2.1 Знакомство с классами Query
Кстати, еще один важный момент – это вспомогательный класс Query. Ты мог его видеть вот в этом примере:
public List<Employee> getAllEmployes() {
try (Session session = sessionFactory.openSession()) {
Query<Employee> query = session.createQuery("from Employee", Employee.class);
return query.list();
}
}
На самом деле, Query – это интерфейс и у него есть несколько реализаций на разные случаи. Но для простоты я буду продолжать называть его классом. Это, скажем так, класс в широком смысле – в терминах ООП.
Примечание. Раньше было два класса:
- Query для описания запроса.
- TypedQuery для описания запроса с заранее известным типом.
Первый появился, когда Hibernate уже был, а дженериков еще не было. Потом, после выхода JDK 5, в Hibernate добавили еще один класс – TypedQuery, который уже поддерживал типизацию результата запроса.
Но, насколько я помню, начиная с 5-й версии Hibernate оставили только один типизированный класс, и он теперь называется Query.
Стандартный способ создания Query:
Query<Employee> query = session.createQuery("from Employee", Employee.class);
Объекты Query ты создавать научился, а как эти запросы выполнить?
Тут все еще проще – мы просто вызываем метод list() у объекта Query:
Query<Employee> query = session.createQuery("from Employee", Employee.class);
List<Employee> resultLіst = query.list();
У метода list() есть JPA-синоним, метод который делает тоже самое, но называется getResultList(). Ты можешь иногда встретить его в коде, написанном другими программистами.
Кстати, если запрос подразумевает, что результат будет в единственном результате, то для вызова запроса проще использовать метод uniqueResult().
Query<Employee> query = session.createQuery("from Employee where id = 1", Employee.class);
Employee result = query.uniqueResult();
У метода uniqueResult() есть JPA-синоним – метод singleResult(). Он появился для совместимости Hibernate со стандартом JPA. Делает он абсолютно то же самое.
2.2 Методы класса Query
На самом деле, у класса Query есть очень много различных методов. Ниже я расскажу еще о трех из них.
Во-первых, это метод stream(). И его JPA-синоним getResultStream().
Оба этих метода возвращают поток данных вместо списка. Такой подход может быть очень эффективным, когда тебе не нужны сразу все объекты, полученные в результате выполнения запроса. Или есть вероятность, что будут использованы только первые из них.
Пример:
Query<Employee> query = session.createQuery("from Employee where id > 100", Employee.class);
Stream<Employee> stream = query.stream();
Второй метод – это метод executeUpdate(). Ты можешь написать запрос, который что-то изменит в базе данных. На этот случай нужно, чтобы Hibernate не использовал read-only транзакцию при обращении к базе данных.
Пример запроса: мы решили поднять уровень всех пользователей на 1.
Query<User> query = session.createQuery("update User set level=level+1", User.class);
int count = query.executeUpdate();
Метод executeUpdate() вернет количество строк, которые реально были изменены.
И наконец третий метод – это scroll(). О нем мы расскажем немного подробнее.
2.3 Методы класса Scroll
Этот метод чем-то похож на метод stream(). Только он позволяет перемещаться по списку результатов, не вытаскивая результаты вообще. То есть ты можешь выполнить запрос, потом проскролить его на миллионную строку результата и начать читать оттуда данные.
Такой продвинутый итератор.
Query<Employee> query = session.createQuery("from Employee where id > 100", Employee.class);
ScrollableResults<Employee> scroll = query.scroll();
У объекта ScrollableResults есть такие методы:
Метод | Описание |
---|---|
R get() | Возвращает текущий элемент |
next() | Перемещает указатель на следующий элемент |
previous() | Перемещает указатель на предыдущий элемент |
scroll(int size) | Скролит на size строк вперед |
position(int pos) | Делает текущим элементом элемент номер pos |
last() | Текущий элемент теперь последний |
first() | Текущий элемент теперь первый |
getRowNumber() | Возвращает номер текущей строки |
setRowNumber() | Устанавливает номер текущей строки |
Допустим, ты выполнил запрос и хочешь получить последний элемент. Вот как это можно сделать:
Query<Employee> query = session.createQuery("from Employee where id > 100", Employee.class);
ScrollableResults<Employee> scroll = query.scroll();
scroll.last();
Employee lastEmployee = scroll.get();
createQuery("update User set level=level+1"); int count = query.executeUpdate(); session.getTransaction().commit(); return count; Но ! @Deprecated Query createQuery(String var1);