Что такое сессия (Session) в Hibernate?

«Что такое сессия (Session) в Hibernate?» — вопрос из категории Hibernate, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Сессия (org.hibernate.Session) — это центральный, короткоживущий объект в Hibernate, который представляет собой обертку вокруг JDBC-соединения и является точкой входа для выполнения операций с базой данных. Это не потокобезопасный объект, который обычно ассоциируется с одним запросом или транзакцией (паттерн "session-per-request").

Ключевые обязанности Session

  1. Кэш первого уровня (L1 Cache): Каждая сессия имеет свой собственный кэш объектов. Повторные обращения к одному и тому же объекту в рамках одной сессии не вызывают лишних SQL-запросов.
  2. Управление жизненным циклом объектов: Сессия отслеживает состояние объектов (transient, persistent, detached, removed).
  3. Координация запросов: Преобразует операции с объектами (save, update) в SQL-запросы.
  4. Обеспечение ленивой загрузки (Lazy Loading): Позволяет отложенно загружать связанные коллекции и прокси-объекты.

Пример типичного использования

// Получение сессии из фабрики (обычно через ThreadLocal)
Session session = sessionFactory.openSession();
Transaction transaction = null;

try {
    transaction = session.beginTransaction();

    // CRUD операции
    User newUser = new User("Alice"); // Transient state
    session.save(newUser); // Persistent state, INSERT запланирован

    User user = session.get(User.class, 1L); // SELECT, объект закеширован в L1
    user.setName("Bob"); // UPDATE запланирован (изменение отслеживается)

    session.delete(user); // DELETE запланирован

    transaction.commit(); // Все запросы выполняются здесь

    // После commit/close объект становится detached
    System.out.println(newUser.getId()); // ID доступен после сохранения

} catch (Exception e) {
    if (transaction != null) transaction.rollback();
    throw e;
} finally {
    session.close(); // Критически важно закрывать сессию!
}

Важные принципы работы

  • Короткий срок жизни: Сессия должна открываться непосредственно перед операцией и закрываться сразу после. Не храните ее открытой.
  • Не потокобезопасна: Никогда не используйте одну сессию в нескольких потоках.
  • Связь с транзакцией: Границы сессии и транзакции часто совпадают, но это не обязательно.
  • Отсоединенные объекты (Detached): После session.close() или session.evict() объекты становятся detached. Их изменения не отслеживаются, для повторного сохранения нужен session.update() или session.merge().