Что такое жизненный цикл сущностей в Hibernate?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Что такое жизненный цикл сущностей в Hibernate?
Жизненный цикл (Entity Lifecycle) в Hibernate — это состояния, которые объект (сущность) проходит от момента создания до удаления, и как Hibernate отслеживает изменения этого объекта для синхронизации с базой данных.
Четыре состояния Entity Lifecycle
┌──────────┐
│ Transient│ Новый объект, не привязан к БД
└─────┬────┘
│ persist() / save()
↓
┌──────────┐
│Persistent│ Объект привязан к сессии, отслеживается
└─────┬────┘
│ evict() / clear()
↓
┌──────────┐
│ Detached │ Объект отделён от сессии, но отслеживается
└─────┬────┘
│ merge()
↓
┌──────────┐
│ Removed │ Объект удалён, но ещё в памяти
└──────────┘
1. Transient (Преходящее состояние)
Объект только что создан в памяти, не связан с БД и не отслеживается Hibernate.
// Объект в состоянии Transient
User user = new User();
user.setName("John");
user.setEmail("john@example.com");
// На этом этапе:
// - Объект существует только в памяти
// - Нет ID (основного ключа) из БД
// - Hibernate не отслеживает изменения
// - При закрытии сессии объект теряется
Как определить Transient:
// Объект без ID = Transient
if (user.getId() == null) {
// Этот объект в состоянии Transient
}
2. Persistent (Постоянное состояние)
Объект привязан к текущей сессии Hibernate, все изменения отслеживаются.
SessionFactory sessionFactory = createSessionFactory();
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
// Переход в Persistent через save()
User user = new User();
user.setName("John");
session.save(user); // Теперь Persistent
// Изменения отслеживаются
user.setEmail("john@example.com");
tx.commit();
session.close();
Характеристики Persistent:
- Объект имеет ID (первичный ключ)
- Привязан к текущей сессии (Session)
- Все изменения отслеживаются
- При commit() все изменения синхронизируются с БД
- Является частью 1st Level Cache
Session session = sessionFactory.openSession();
// Получение объекта из БД → автоматически Persistent
User user = session.get(User.class, 1L);
// Изменение
user.setEmail("new@example.com");
// Commit → изменения в БД (UPDATE)
session.getTransaction().commit();
3. Detached (Отделённое состояние)
Объект был Persistent, но сессия закрыта. Объект остаётся в памяти, но Hibernate больше его не отслеживает.
Session session = sessionFactory.openSession();
User user = session.get(User.class, 1L); // Persistent
session.close(); // Сессия закрыта → Detached
// Объект всё ещё в памяти
System.out.println(user.getName()); // ✅ Работает
// Но Hibernate не отслеживает изменения
user.setEmail("new@example.com");
// Эта изменение НЕ попадёт в БД автоматически!
session.close();
// По закрытии сессии: user переходит в Detached
Проблема Detached:
User user = getUserFromPreviousSession(); // Detached
user.setEmail("new@example.com");
Session session = sessionFactory.openSession();
session.beginTransaction();
session.getTransaction().commit();
session.close();
// Изменение в user ПОТЕРЯНО! Сессия не знает о Detached объекте
4. Removed (Удалённое состояние)
Объект удалён из БД и из сессии, но ещё находится в памяти.
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
User user = session.get(User.class, 1L); // Persistent
session.delete(user); // Removed
// На этом этапе запис удалена из БД при commit()
tx.commit();
session.close();
// Объект всё ещё в памяти (может проверить значения)
System.out.println(user.getName()); // ✅ Работает
// Но это просто объект в памяти, БД уже не знает о нём
Переходы между состояниями
// 1. TRANSIENT → PERSISTENT
Session session = sessionFactory.openSession();
User user = new User(); // Transient
session.save(user); // Persistent ✓
// 2. PERSISTENT → DETACHED
session.close(); // Persistent → Detached ✓
// 3. DETACHED → PERSISTENT (через merge)
Session newSession = sessionFactory.openSession();
User managedUser = newSession.merge(user); // Detached → Persistent ✓
// 4. PERSISTENT → REMOVED
newSession.delete(managedUser); // Persistent → Removed ✓
newSession.getTransaction().commit();
// 5. PERSISTENT → DETACHED (через evict)
Session session = sessionFactory.openSession();
User user = session.get(User.class, 1L); // Persistent
session.evict(user); // Persistent → Detached ✓
Методы управления состояниями
save()
Session session = sessionFactory.openSession();
User user = new User(); // Transient
Long id = (Long) session.save(user); // Transient → Persistent, возвращает ID
user.getId(); // Теперь есть ID
persist()
User user = new User(); // Transient
session.persist(user); // Transient → Persistent (не возвращает ID)
get() / load()
User user = session.get(User.class, 1L); // Transient → Persistent (из БД)
merge()
User detachedUser = ...; // Detached
User managedUser = session.merge(detachedUser); // Detached → Persistent
// ВАЖНО: изменения переходят в managedUser, не в detachedUser!
detachedUser.setName("NEW"); // ❌ Не будет сохранено
managedUser.setName("NEW"); // ✅ Будет сохранено
evict()
User user = session.get(User.class, 1L); // Persistent
session.evict(user); // Persistent → Detached
user.setName("NEW"); // Изменение не отслеживается
delete() / remove()
User user = session.get(User.class, 1L); // Persistent
session.delete(user); // Persistent → Removed
session.getTransaction().commit();
1st Level Cache и Lifecycle
Hibernate отслеживает Persistent объекты в 1st Level Cache (сессии):
Session session = sessionFactory.openSession();
// Первый запрос → SQL в БД
User user1 = session.get(User.class, 1L);
// Второй запрос → из кеша (нет SQL)
User user2 = session.get(User.class, 1L);
// Проверка: это один и тот же объект
System.out.println(user1 == user2); // true (из кеша)
session.close(); // Очищение кеша → объекты в Detached
Практический пример
public void updateUser(Long userId, String newEmail) {
// Сессия 1
Session session1 = sessionFactory.openSession();
Transaction tx1 = session1.beginTransaction();
User user = session1.get(User.class, userId); // Persistent
user.setEmail(newEmail);
tx1.commit();
session1.close(); // user → Detached
// Сессия 2
Session session2 = sessionFactory.openSession();
Transaction tx2 = session2.beginTransaction();
// Вариант 1: НЕ работает (user всё ещё Detached)
// user.setName("John"); // Изменение потеряется!
// Вариант 2: Правильно (merge)
User managedUser = session2.merge(user); // Detached → Persistent
managedUser.setName("John");
tx2.commit();
session2.close();
}
Важные правила
1. Persistent объекты отслеживаются
User user = session.get(User.class, 1L);
user.setName("New Name"); // Hibernate видит это изменение
session.getTransaction().commit(); // UPDATE автоматически
2. Detached изменения требуют merge
User detached = ...; // Из другой сессии
detached.setName("NEW"); // Это не сохранится
User managed = session.merge(detached); // Нужен merge!
managed.setName("NEW"); // Теперь сохранится
3. Сессия = Transaction
Session session = sessionFactory.openSession();
// Без beginTransaction() изменения не сохранятся!
Transaction tx = session.beginTransaction();
User user = session.get(User.class, 1L);
user.setName("NEW");
tx.commit(); // Только здесь сохранится
4. Cascade операции
@Entity
public class Post {
@OneToMany(cascade = CascadeType.ALL)
List<Comment> comments;
}
// Если post → Persistent, то и comments → Persistent
session.save(post); // Сохранит и post, и все comments
Заключение
Жизненный цикл сущностей в Hibernate — это фундаментальный концепт для понимания, как ORM синхронизирует объекты с БД. Правильное управление состояниями (Transient, Persistent, Detached, Removed) критично для предотвращения потери данных и оптимизации производительности приложения.