Я хотел бы указать ответ @Andronicus, потому что ответ не точный.
LazyInitializationException
Он не связан строго с @Transactional
, транзакциями или открытием / закрытые соединения. Поведение довольно просто (есть псевдокод ниже)
Без LazyInitializationException
Context context = Hibernate.openPersistentContext();
Payment payment = context.getById(1L, Payment.class);
Debtor debtor = payment.getDebtor();
Hibernate.closePersistentContext();
С LazyInitializationException
Context context = Hibernate.openPersistentContext();
Payment payment = context.getById(1L, Payment.class);
Hibernate.closePersistentContext();
Debtor debtor = payment.getDebtor();
Вопросы
Так почему, черт возьми, я всегда получаю исключение HibernateLazyLoading, которое обязывает меня написать пользовательский запрос на выборку в репозитории PaymentRepository, замедляя мой первоначальный запрос, поскольку я бы использовал EAGER FetchType?
Потому что Hibernate.closePersistentContext()
произошло где-то раньше.
Так почему же этот FetchType.LAZY существует, если он не работает так, как ожидалось?
Потому что нам не всегда нужен полностью net графа сущностей. Мы можем использовать JPQL (HQL), критерии и прогнозы для загрузки частей сущности. Нам нужно объяснить Hibernate, как связаны сущности, поэтому нам нужно добавить ассоциации, например @ManyToOne
.
Здесь есть небольшая проблема: отображение служит для двух целей
- Объясните Hibernate, как связаны сущности
- Сохраните / Загрузите сущности
Итак, самый простой способ отключить загрузку от сопоставления объектов - это FetchType.LAZY
.
Простое правило
Всегда используйте FetchType.LAZY
везде и извлекайте необходимые части графа сущностей в том месте, где он необходим.