1. Знайомство з класами Query
До речі, ще один важливий момент — це допоміжний клас Query. Ти міг його бачити ось у цьому прикладі:
public List<Employee> getAllEmployees() {
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> resultList = 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. Методи класу 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(). Про нього ми розповімо трохи докладніше.
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();