Что такое ленивая загрузка (Lazy Loading) в Hibernate?

«Что такое ленивая загрузка (Lazy Loading) в Hibernate?» — вопрос из категории Hibernate, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Ленивая загрузка (Lazy Loading) в Hibernate — это стратегия отложенной загрузки связанных сущностей или коллекций. Данные загружаются не сразу при получении родительского объекта, а только при первом прямом обращении к ним. Это стандартный и рекомендуемый подход для оптимизации производительности.

Как работает: При загрузке сущности Hibernate возвращает прокси-объект для связанных полей с FetchType.LAZY. Реальный SQL-запрос к базе данных выполняется в момент первого вызова метода геттера этого поля.

Пример настройки:

@Entity
public class Order {
    @Id
    private Long id;

    // Коллекция загрузится только при вызове getItems()
    @OneToMany(fetch = FetchType.LAZY, mappedBy = "order")
    private List<OrderItem> items;
    // ...
}

Ключевая проблема — LazyInitializationException: Исключение возникает при попытке доступа к ленивой коллекции вне контекста открытой сессии (Session) или транзакции. Прокси не может выполнить запрос к БД.

Способы решения (загрузки данных до закрытия сессии):

  1. JOIN FETCH в HQL/JPQL: SELECT o FROM Order o JOIN FETCH o.items WHERE o.id = :id
  2. Использование EntityGraph.
  3. Вызов Hibernate.initialize(proxy) внутри сессии.

По умолчанию: @OneToMany и @ManyToMany — LAZY, @ManyToOne и @OneToOne — EAGER (но для @OneToOne с optional=false тоже EAGER). Рекомендуется везде использовать LAZY и загружать связи явно, когда они нужны.