Hibernate
Hibernate — ORM-провайдер для Java. Он реализует Jakarta Persistence (JPA), строит SQL по отображению классов на таблицы и синхронизирует состояние объектов с базой данных.
Главное различие:
- JPA задаёт контракт:
EntityManager, аннотации и правила жизненного цикла; - Hibernate реализует этот контракт и добавляет собственные возможности;
- JDBC остаётся нижним уровнем, через который в итоге выполняется SQL.
См. JPA Hibernate ORM и JPA Hibernate и JDBC сравнение интерфейсов.
Что происходит при работе
- Приложение открывает транзакцию.
EntityManagerзагружает сущность и помещает её в Persistence Context.- Hibernate хранит снимок загруженного состояния.
- При
flushсравнивает снимок с текущим объектом — это dirty checking. - Формирует
INSERT,UPDATEиDELETE, учитывая порядок зависимостей. - JDBC-драйвер отправляет команды базе.
flush синхронизирует контекст с БД, но не обязательно фиксирует транзакцию. commit фиксирует её и перед этим обычно вызывает flush.
За что платим
- скрытая генерация SQL усложняет оценку стоимости запроса;
- ленивые связи требуют живого контекста;
- каскады могут сохранить или удалить больше данных, чем ожидалось;
- неудачный
fetch joinразмножает строки; - пакетная обработка без
flushиclearраздувает память; - массовый JPQL/SQL-апдейт обходит состояние уже загруженных сущностей.
Поэтому ORM не отменяет знание SQL, индексов и плана выполнения.
Практический минимум
- включать SQL и статистику на диагностическом окружении;
- явно выбирать границу транзакции;
- по умолчанию загружать только нужные связи;
- для списка проецировать данные в DTO, если сущность не нужна;
- контролировать число запросов тестом или метрикой;
- не использовать
equalsиhashCode, зависящие от изменяемых полей.
Вопросы для повторения
- Hibernate и JPA — одно и то же? Нет. JPA — спецификация, Hibernate — один из её провайдеров.
- Когда выполняется SQL? Не обязательно в момент вызова
persistили изменения поля; обычно приflush, перед запросом либо при commit. - Зачем нужен persistence context? Он гарантирует идентичность объекта в пределах контекста, отслеживает изменения и откладывает запись.
- Почему ORM создаёт N+1? Сначала загружается список сущностей, затем для каждой ленивой связи выполняется отдельный запрос.
- Можно ли полностью забыть JDBC? Нет: ограничения драйвера, транзакции, batch и фактический SQL остаются частью системы.
Связано: EntityManager, Жизненный цикл Entity в Hibernate, Fetch type Hibernate, Кэширование hibernate, Кейс N plus 1 при обходе иерархии.