Вопрос 16 · Раздел 16

Что такое EntityManager и чем он отличается от Session

EntityManager и Session — два интерфейса для работы с ORM в Java. EntityManager — это стандартный JPA интерфейс, а Session — Hibernate-специфичная реализация. Понимание различий...

Версии по языкам: English Russian Ukrainian

Обзор

EntityManager и Session — два интерфейса для работы с ORM в Java. EntityManager — это стандартный JPA интерфейс, а Session — Hibernate-специфичная реализация. Понимание различий помогает правильно выбирать абстракцию.


🟢 Junior Level

Что такое EntityManager

EntityManager — это JPA стандартный интерфейс для работы с сущностями. Он определён в спецификации JPA и работает с любым JPA провайдером (Hibernate, EclipseLink, OpenJPA).

Примечание: в Hibernate 5 / Java EE используется пакет javax.persistence, в Hibernate 6 / Jakarta EE — jakarta.persistence. Примеры ниже используют jakarta.

// JPA стандарт — работает с любым провайдером
@PersistenceContext
private EntityManager em;

em.persist(user);
em.merge(user);
em.remove(user);
User found = em.find(User.class, 1L);

Что такое Session

Session — это Hibernate-специфичный интерфейс. Он предоставляет дополнительные возможности, которые не доступны в стандартном JPA.

// Hibernate специфика
Session session = entityManager.unwrap(Session.class);
session.save(user);
session.update(user);
session.delete(user);
User found = session.get(User.class, 1L);

Основная разница

  EntityManager Session
Стандарт JPA (java.persistence) Hibernate (org.hibernate)
Переносимость Любой JPA провайдер Только Hibernate
Методы persist, merge, remove, find save, update, delete, get
Доп. возможности Нет doWork(), replicate(), и др.

Как получить Session из EntityManager

Session session = entityManager.unwrap(Session.class);

🟡 Middle Level

Сравнение методов

EntityManager (JPA)          Session (Hibernate)
─────────────────           ─────────────────
persist()                   save()
merge()                     update(), saveOrUpdate()
remove()                    delete()
find()                      get()
createQuery()               createQuery()
createNativeQuery()         createSQLQuery()
flush()                     flush()
clear()                     clear()
contains()                  contains()
detach()                    evict()
refresh()                   refresh()

Когда использовать EntityManager

// Для переносимости между JPA провайдерами
@Repository
public class UserRepository {
    @PersistenceContext
    private EntityManager em;

    public void save(User user) {
        em.persist(user);  // стандартный метод
    }
}

Когда использовать Session

// Для Hibernate-специфичных возможностей
Session session = entityManager.unwrap(Session.class);

// Прямая работа с Connection
session.doWork(connection -> {
    // JDBC операции
    PreparedStatement stmt = connection.prepareStatement("...");
});

// Batch operations
session.doReturningWork(connection -> {
    // вернуть результат
    return result;
});

// Native Hibernate возможности
session.byMultipleIds(User.class)
    .multiLoad(ids);

Дополнительные методы Session

Session session = entityManager.unwrap(Session.class);

// doWork — работа с Connection
session.doWork(new Work() {
    public void execute(Connection connection) {
        // JDBC операции
    }
});

// replicate — копирование сущности
session.replicate(user, ReplicationMode.OVERWRITE);

// getIdentifier — получить ID
Serializable id = session.getIdentifier(user);

// isConnected — проверка соединения
boolean connected = session.isConnected();

🔴 Senior Level

Внутренняя реализация

// В Hibernate 5.2+ Session и EntityManager используют общую внутреннюю
// реализацию. Session implements EntityManager, а не оборачивает его.

EntityManager — интерфейс из JPA спецификации (jakarta.persistence)
Session — интерфейс из Hibernate (org.hibernate)

Когда стоит использовать Session

// 1. Native SQL с возвратом результата
Session session = entityManager.unwrap(Session.class);
NativeQuery<User> query = session.createNativeQuery(
    "SELECT * FROM users WHERE created_at > :date", User.class);
query.setParameter("date", date);

// 2. Multi-load (Hibernate 5.1+)
List<User> users = session.byMultipleIds(User.class)
    .enableCheckCache(true)
    .multiLoad(List.of(1L, 2L, 3L));

// 3. Scrollable results (для больших данных)
ScrollableResults<User> results = session.createQuery("FROM User", User.class)
    .setFetchSize(100)
    .scroll(ScrollMode.FORWARD_ONLY);

// 4. Statistics
Statistics stats = session.getSessionFactory().getStatistics();

Когда НЕ стоит использовать Session

// ❌ Если не нужны Hibernate-специфичные фичи
// ❌ Если возможна смена провайдера
// ❌ Для стандартных CRUD операций
// ❌ В библиотеках/фреймворках (нарушает абстракцию)

Best Practices

✅ EntityManager по умолчанию
✅ unwrap(Session) когда нужны Hibernate-фичи
✅ Стандартные методы для переносимости
✅ Session для batch/native operations
✅ Session для statistics и monitoring

❌ Session если не нужны Hibernate-фичи
❌ Смешивание без причины
❌ unwrap() в каждом методе (лучше вынести)
❌ Прямое использование Session в библиотеках

🎯 Шпаргалка для интервью

Обязательно знать:

  • EntityManager — JPA стандарт (jakarta.persistence), работает с любым провайдером
  • Session — Hibernate-специфичный интерфейс, дополнительные возможности
  • Session можно получить через entityManager.unwrap(Session.class)
  • Методы EntityManager: persist, merge, remove, find; Session: save, update, delete, get
  • Session предоставляет: doWork() (JDBC), multi-load, scrollable results, statistics
  • EntityManager по умолчанию, Session когда нужны Hibernate-фичи

Частые уточняющие вопросы:

  • Когда использовать Session? Native SQL с возвратом, multi-load, scrollable results, statistics, batch operations
  • Когда НЕ использовать Session? Стандартные CRUD, возможна смена провайдера, библиотеки/фреймворки
  • doWork() зачем? Прямой доступ к JDBC Connection для операций которые JPA не поддерживает
  • В Hibernate 5.2+ что изменилось? Session и EntityManager используют общую внутреннюю реализацию

Красные флаги (НЕ говорить):

  • «Всегда использую Session вместо EntityManager» — привязка к Hibernate
  • «Смешиваю без причины» — нарушает абстракцию JPA
  • «unwrap() в каждом методе» — лучше вынести в отдель компонент
  • «Session в библиотеках» — нарушает переносимость

Связанные темы:

  • [[7. Опишите жизненный цикл Entity в Hibernate]]
  • [[14. В чём разница между persist() и merge()]]
  • [[12. Что такое dirty checking в Hibernate]]
  • [[17. Как реализовать оптимистичную блокировку в JPA]]