Persistence Context
Persistence context — набор сущностей, которыми EntityManager управляет как одной единицей работы. В Hibernate ближайшее понятие — first-level cache внутри Session.
Три свойства, которые важно помнить
Идентичность
В одном контексте сочетанию «класс + первичный ключ» соответствует один managed-экземпляр:
User first = em.find(User.class, 42L);
User second = em.find(User.class, 42L);
assert first == second;Это не означает, что повторный запрос никогда не уйдёт в БД: запрос может выполниться, но результат будет сведен к уже managed-объекту.
Dirty checking
Провайдер запоминает состояние при загрузке и перед flush обнаруживает изменения. Для managed-сущности не нужен отдельный update.
Write-behind
Команды на запись накапливаются до flush. Это позволяет упорядочивать SQL и собирать batch, но ошибка ограничения может проявиться позже строки кода, которая изменила объект.
Границы контекста
Обычно контекст живёт одну транзакцию. Паттерн Open Session in View продлевает его до конца HTTP-запроса и позволяет ленивую загрузку в контроллере или сериализаторе, но скрывает дополнительные запросы. Надёжнее загрузить нужные данные внутри сервисной транзакции.
При пакетной обработке:
for (int i = 0; i < items.size(); i++) {
em.persist(items.get(i));
if (i > 0 && i % 100 == 0) {
em.flush();
em.clear();
}
}Вопросы для повторения
- Первый уровень кэша можно отключить? Нет для managed-сущностей: это основа JPA-контекста.
- Почему контекст раздувает память? Он удерживает ссылки и снимки всех managed-сущностей.
- Что делает
clear? Отсоединяет все сущности; после него dirty checking их не сохранит. - Равен ли flush commit? Нет: flush отправляет SQL, а commit фиксирует транзакцию.
- Почему bulk update опасен? Он меняет строки напрямую, а уже загруженные объекты остаются устаревшими.
Связано: EntityManager, Жизненный цикл Entity в Hibernate, Кэширование hibernate.