1. Транзакції та цілісність бази даних
Звичайний режим роботи бази даних — це коли до неї щохвилини приходять тисячі запитів від сотень різних клієнтів. За такої умови часто виникають ситуації, коли до тих самих даних йде звернення з різних запитів.
Рідше, але, знов-таки, час від часу виникають ситуації, коли один запит читає певний рядок, а інший запит у цей час змінює його. Уяви, що буде, якщо хтось прочитає рядок, який змінено лише наполовину? Нічого хорошого.
Цю проблему вирішують декількома способами. По-перше, можна просто лочити рядок, який змінюється. І для читання, і запису. Цей спосіб працює, але швидкість бази сильно страждає.
Другий спосіб — це лочити рядок лише на запис. А проте все одно буде проблема, коли хтось спробує прочитати частково змінений рядок. Висновок — не повинно бути ситуації, коли рядок частково змінено.
Тому вигадали третій спосіб — транзакції. Транзакція — це група дій, які виконуються або всі разом, або жодна з них. Не може бути ситуації, коли частина дій виконалася, а друга — ні. Якщо не вдається внести всі зміни, то всі вже внесені відкочуються назад.
Будь-який сучасний SQL-сервер дозволяє змінювати дані лише у транзакціях. Ти відкриваєш транзакцію, вносиш будь-які зміни до будь-якої кількості таблиць, і комітиш транзакцію. Потім SQL-сервер намагається внести зміни. Якщо все просто добре, то вони додадуться до загальної бази даних. Якщо були проблеми, всі зміни скасовуються.
Hibernate також використовує цю парадигму. Саме тому у попередній лекції ми побачили, під час спроби зберегти об'єкт Employee до бази спочатку відкривалася транзакція, а після збереження — комітилася.
Ми ще розберемо цю тему детальніше, а наразі просто знай, навіщо транзакції потрібні і де вони зазвичай використовуються.
2. Отримання об'єктів
Якщо Hibernate виконує запит на отримання даних, явно транзакцію відкривати не потрібно. Hibernate сам це зробить, якщо вважатиме за потрібне: у нього є його налаштування, а також налаштування SQL-сервера.
Ми з тобою розберемо способи роботи з базою даних. І найпростіший з них — це отримання об'єкта за його ID. Для цього потрібно використовувати метод get()
в об'єкті session. Загальний вигляд такого запиту:
Клас ім'я = session.get(Клас.class, ID);
Приклад:
public User getUserById(Integer id) {
try (Session session = sessionFactory.openSession()) {
User user = session.get(User.class, id);
return user;
}
}
3. Збереження (додавання) об'єктів
Якщо ти хочеш зберегти свій об'єкт у базі даних, то на рівні SQL виконається запит INSERT. Тому твої дії слід виконувати у вигляді окремої транзакції. До того ж, для збереження краще використовувати метод persist()
об'єкта session.
Загальний вигляд такого запиту:
session.persist(Об'єкт);
Метод persist()
змінює не лише базу, а й сам об'єкт. Вся справа в тому, що коли ми додаємо об'єкт до бази, то до додавання цього об'єкта ще немає свого ID. Ну, зазвичай так відбувається, хоч бувають нюанси. А після додавання до об'єкту ID вже є.
public boolean saveUser(User user) {
try (Session session = sessionFactory.openSession()) {
Transaction transaction = session.beginTransaction();
session.persist(user);
transaction.commit();
return true;
}
catch() {
return false;
}
}
Також об'єкт Session має метод save()
, який виконує аналогічну функцію. Просто метод save()
— це старий стандарт Hibernate, а метод persist()
— це стандарт JPA.
4. Видалення об'єктів
Якщо ти хочеш видалити існуючий об'єкт, зробити це дуже просто. Для цього об'єкт session має спеціальний метод — remove()
.
Загальний вигляд такого запиту:
session.remove(Об'єкт);
І, звісно, напишемо код з прикладом:
public boolean removeUser(User user) {
try (Session session = sessionFactory.openSession()) {
Transaction transaction = session.beginTransaction();
session.remove(user);
transaction.commit();
return true;
}
catch() {
return false;
}
}
Навіщо так складно, запитаєш ти?
Ну, по-перше, будь-які зміни бази даних завжди несуть за собою різні та не завжди очевидні наслідки. А по-друге, у цього об'єкта могли бути пов'язані з ним дочірні об'єкти тощо. Тому сценарії видалення часто бувають нетривіальними.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ