Hibernate Session

Здесь Session — Hibernate persistence context, а не HTTP session. Он связывает Java-объекты с записями БД, отслеживает изменения и координирует SQL в рамках единицы работы.

Жизненный цикл

try (Session session = sessionFactory.openSession()) {
    Transaction tx = session.beginTransaction();
    try {
        Order order = session.find(Order.class, 42L);
        order.markPaid();
        tx.commit();
    } catch (RuntimeException ex) {
        tx.rollback();
        throw ex;
    }
}

После find entity становится managed. Hibernate делает dirty checking и обычно формирует UPDATE при flush. commit вызывает flush, но flush не равен commit: SQL может уйти в БД, а транзакция затем откатиться.

Состояния entity

  • transient — новый объект вне persistence context;
  • managed/persistent — отслеживается текущей Session;
  • detached — был managed, но Session закрыта/очищена;
  • removed — помечен на удаление.

Первая identity map Session гарантирует, что повторная загрузка одной строки в этом контексте обычно возвращает тот же Java object. Это не общий application cache.

Session и transaction

Session можно технически держать дольше одной transaction, но безопасная модель сервиса — короткая единица работы и явная transaction boundary. Обычная JDBC-транзакция не становится вложенной от второго вызова beginTransaction. В Spring semantics вложенности определяет transaction manager и propagation; NESTED обычно опирается на savepoint, если он поддерживается.

Session не thread-safe. Нельзя передавать её между параллельными задачами.

Lazy loading

Lazy proxy/collection требует открытого persistence context. Если слой web трогает связь после закрытия Session, возникает LazyInitializationException. Исправление — загрузить нужную проекцию или association внутри транзакции, а не держать Session открытой без границ.

Типичные сбои

  • Открыть transaction и забыть rollback при исключении.
  • Путать flush с успешным commit.
  • Сериализовать managed entity вместе с ленивым графом.
  • Разделять Session между threads.
  • Загружать тысячи managed entities и раздувать first-level cache.
  • Использовать merge, не понимая, что возвращается managed copy, а переданный object остаётся detached.

Вопросы для собеседования

Что хранит persistence context? Managed entities и их identity/снимки, необходимые для dirty checking.

Чем flush отличается от commit? Flush синхронизирует изменения с БД в текущей transaction, commit окончательно фиксирует её.

Session thread-safe? Нет.

Почему возникает LazyInitializationException? Lazy association пытаются загрузить без доступной Session.

Что произойдёт с managed entity после изменения поля? При flush Hibernate обнаружит dirty state и сформирует SQL, если изменение отображается и transaction позволяет.

См. Hibernate, Transactional, Каскадные обновления.