1. Можливі варіанти статусу об'єкта
Як ти вже, напевно, звернув увагу, коли об'єкт приєднаний до Hibernate, його стан називається Persistent або Managed. Як правильно? Persist чи Managed?
Можна і так, і так. Згідно зі специфікацією JPA, об'єкт має статус Persist, а згідно зі специфікацією Hibernate його стан називається Managed.
У Hibernate робота з базою ведеться через об'єкт типу org.hibernate.Session. Відповідно до JPA, клас має називатися javax.persistence.EntityManager. Насправді великої проблеми тут немає, тому що обидва типи є інтерфейсами.
Інтерфейс org.hibernate.Session оголошено так:
interface Session extends java.lang.AutoCloseable, javax.persistence.EntityManager, HibernateEntityManager, QueryProducer, java.io.Serializable, SharedSessionContract {
}
Тому в інтерфейсі Session є всі методи, які є в інтерфейсі EntityManager. Але також є і свої, які дісталися йому від попередніх версій Hibernate, коли ще не було специфікації JPA.
Описується ця вся ситуація ось такою картинкою:
Давай розберемо всі методи, які є у інтерфейсу session, а також нюанси їхньої роботи.
2. Нюанси роботи методу persist()
Під час збереження об'єкта до бази даних потрібно пам'ятати дві речі.
По-перше, збереження об'єкта врешті-решт призведе до виконання однієї з команд SQL: INSERT або UPDATE. По-друге, ці дії відбудуться не одразу після виклику методу об'єкта session, а лише після закриття транзакції.
Давай розглянемо якусь просту ситуацію. Наприклад, у тебе є клас User:
@Entity
public class User {
@Id
@GeneratedValue
public Integer id;
@Columnt(name="user_name")
public String name;
}
Давай збережемо до бази його об'єкт за допомогою методу persist().
User user = new User();
user.setName("Колян");
session.persist(user);
Завдання цього методу — зберегти новий об'єкт у базі даних. Якщо такого об'єкта ще немає, він додасться до бази через виклик SQL-методу INSERT.
Якщо ж об'єкт вже є в базі, то нічого не станеться. Однак можливий ще й третій випадок — спроба зберегти до бази об'єкт зі статусом Detached. І тут кинеться виняток. Приклад:
User user = new User();
user.setName("Колян");
session.persist(user);
session.evict(user); // від'єднуємо об'єкт від сесії
session.persist(user); // Тут кинеться виняток PersistenceException!
3. Нюанси роботи методу save()
Метод save() дістався нинішньому Hibernate від попередніх версій. За своєю суттю він дуже схожий на метод persist(): він також додає новий запис до таблиці за допомогою методу INSERT. Однак він має кілька цікавих нюансів.
По-перше, цей метод повертає значення — нове ID об'єкта. Як ти вже знаєш, зазвичай до додавання в базу об'єктів немає ID, і воно присвоюється вже базою даних. Так ось, метод save() об'єкта session повертає ID, яка була присвоєна об'єкту, що зберігається.
Важливо! Відповідно до специфікації Hibernate, ID може бути будь-який об'єкт, що серіалізується — не тільки число. Це може бути рядок, число, enum — взагалі будь-що, що можна повністю покласти в одну колонку таблиці в базі.
Метод save() має тип результату Serialized, тому його результат потрібно приводити до правильного типу:
User user = new User();
user.setName("Колян");
Integer id = (Integer) session.save(user);
Також метод save() має іншу поведінку у випадку з Detached станом об'єкта. Такий об'єкт він розглядає як новий і додає ще один запис:
User user = new User();
user.setName("Колян");
Integer id = (Integer) session.save(user);
session.evict(user); // від'єднуємо об'єкт від сесії
Integer id2 = (Integer) session.save(user);
Змінні id та id2 будуть відрізнятися. У таблиці в базі даних буде додано два записи: по одному для кожної операції save().
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ