Что такое EntityManager и чем он отличается от Session
EntityManager и Session — два интерфейса для работы с ORM в Java. EntityManager — это стандартный JPA интерфейс, а Session — Hibernate-специфичная реализация. Понимание различий...
Обзор
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]]