Паттерны в Hibernate
Hibernate сочетает несколько архитектурных паттернов. Название помогает понять ответственность, но реализация содержит дополнительные правила ORM.
Data Mapper
Mapper переносит состояние между объектной и реляционной моделями, не заставляя entity самостоятельно выполнять SQL.
Entity ↔ Persistence Context / Mapper ↔ Database rowВ отличие от Active Record, entity обычно не содержит save() или delete() для обращения к БД.
См. JPA Hibernate ORM и Маппинг Hibernate.
Identity Map
Внутри одного Persistence Context одной database identity соответствует один managed Java-object:
Order first = entityManager.find(Order.class, 42L);
Order second = entityManager.find(Order.class, 42L);
assert first == second;Это позволяет dirty checking сравнивать изменения управляемого экземпляра и предотвращает две противоречивые копии одной строки внутри context.
Unit of Work
Persistence Context накапливает изменения managed entities и синхронизирует их с БД при flush. Код меняет объект, а SQL может выполниться позже.
@Transactional
public void rename(long id, String name) {
Order order = entityManager.find(Order.class, id);
order.rename(name);
// UPDATE сформируется при flush/commit
}Flush не равен commit: SQL может уже уйти в БД, но транзакция ещё способна откатиться.
Proxy
Proxy позволяет представить ленивую ссылку без немедленной загрузки. Обращение к данным может выполнить SQL.
Ограничения:
- context должен быть доступен;
- метод не должен быть
final, если proxy строится через subclass; equals, logging и serialization способны случайно инициировать загрузку;- proxy не решает N+1.
Factory
EntityManagerFactory создаёт EntityManager. В native Hibernate аналогичную роль играет SessionFactory.
Factory тяжёлая и обычно живёт всё приложение. EntityManager/Session короткоживущие и не должны совместно использоваться потоками.
Repository и DAO
Repository выражает операции над aggregate/domain objects. DAO ближе к persistence API и таблицам. В маленьком приложении реализации могут выглядеть одинаково, но намерение различается.
Вопросы для собеседования
- Какой паттерн даёт один объект на identity внутри context? Identity Map.
- Почему UPDATE выполняется без
save? Managed entity участвует в Unit of Work и dirty checking. - Является ли lazy proxy загруженной entity? Он представляет ссылку, а состояние может быть ещё не загружено.
- Можно ли разделять EntityManager между потоками? Нет.
- Flush фиксирует транзакцию? Нет.