Lazy Loading (ленивая загрузка) — это стратегия, при которой данные загружаются только тогда, когда они действительно нужны. В контексте Hibernate это означает, что связанные сущности или коллекции не загружаются из базы данных до тех пор, пока к ним не будет явного обращения. Это позволяет оптимизировать производительность, уменьшая количество запросов к базе данных и объем данных, передаваемых между приложением и базой данных.
Hibernate использует прокси-объекты для реализации ленивой загрузки. Когда вы запрашиваете сущность, Hibernate возвращает не сам объект, а его прокси. Прокси — это объект-заглушка, который выглядит как реальная сущность, но на самом деле не содержит данных. Когда вы обращаетесь к полю или методу прокси-объекта, Hibernate выполняет запрос к базе данных, чтобы загрузить реальные данные.
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@OneToMany(mappedBy = "user", fetch = FetchType.LAZY)
private List<Order> orders;
// Getters and setters
}
@Entity
public class Order {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String productName;
@ManyToOne
@JoinColumn(name = "user_id")
private User user;
// Getters and setters
}
Когда вы загружаете сущность User
, Hibernate не загружает связанные сущности Order
сразу. Вместо этого он создает прокси для коллекции orders
. Прокси-коллекция будет загружена только при первом обращении к ней.
User user = session.get(User.class, 1L); // Загружаем пользователя
System.out.println(user.getName()); // Доступ к полю name, данные загружены
List<Order> orders = user.getOrders(); // Прокси-коллекция, данные еще не загружены
System.out.println(orders.size()); // Обращение к коллекции, данные загружаются
Одной из основных проблем ленивой загрузки является LazyInitializationException
. Это исключение возникает, когда вы пытаетесь получить доступ к лениво загруженным данным вне сессии Hibernate.
User user = session.get(User.class, 1L);
session.close(); // Сессия закрыта
List<Order> orders = user.getOrders(); // LazyInitializationException
User user = session.get(User.class, 1L);
Hibernate.initialize(user.getOrders()); // Явная инициализация коллекции
session.close();
List<Order> orders = user.getOrders(); // Данные уже загружены
По умолчанию Hibernate использует ленивую загрузку для коллекций и @ManyToOne
/@OneToOne
ассоциаций. Однако вы можете явно указать стратегию загрузки с помощью аннотации @Fetch
.
@OneToMany(mappedBy = "user", fetch = FetchType.LAZY)
@Fetch(FetchMode.SUBSELECT)
private List<Order> orders;
LazyInitializationException
.Lazy Loading в Hibernate — это мощный механизм, который позволяет оптимизировать загрузку данных, загружая их только тогда, когда они действительно нужны. Он реализуется через прокси-объекты, что позволяет избежать лишних запросов к базе данных. Однако важно учитывать возможные проблемы, такие как LazyInitializationException
, и правильно настраивать стратегии загрузки в зависимости от требований вашего приложения.