Рубрики
Без рубрики

Нетерпеливая/Ленивая Загрузка В Спящем Режиме

Быстрое и практическое знакомство с различными подходами к загрузке данных – ленивыми и нетерпеливыми – в режиме гибернации.

Автор оригинала: baeldung.

1. введение

При работе с ORM извлечение/загрузка данных может быть разделена на два типа: нетерпеливая и ленивая.

В этой краткой статье мы укажем на различия и покажем, что их можно использовать в режиме гибернации.

2. Зависимости Maven

Чтобы использовать Hibernate, давайте сначала определим основную зависимость в вашем pom.xml :


    org.hibernate
    hibernate-core   
    5.2.2.Final

Последнюю версию Hibernate можно найти здесь .

3. Нетерпеливая и ленивая загрузка

Первое, что мы должны обсудить здесь, – это то, что такое ленивая загрузка и нетерпеливая загрузка:

  • Нетерпеливая загрузка – это шаблон проектирования, в котором инициализация данных происходит на месте
  • Ленивая загрузка – это шаблон проектирования, который используется для отсрочки инициализации объекта до тех пор, пока это возможно

Давайте посмотрим, как это на самом деле работает, на некоторых примерах:

Пользователь Ленивый Класс :

@Entity
@Table(name = "USER")
public class UserLazy implements Serializable {

    @Id
    @GeneratedValue
    @Column(name = "USER_ID")
    private Long userId;

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "user")
    private Set orderDetail = new HashSet();

    // standard setters and getters
    // also override equals and hashcode

}

Класс OrderDetail :

@Entity
@Table (name = "USER_ORDER")
public class OrderDetail implements Serializable {
    
    @Id
    @GeneratedValue
    @Column(name="ORDER_ID")
    private Long orderId;
    
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name="USER_ID")
    private UserLazy user;

    // standard setters and getters
    // also override equals and hashcode

}

Один Пользователь может иметь несколько Деталей заказа . В стратегии быстрой загрузки, если мы загрузим данные Пользователя , он также загрузит все связанные с ним заказы и сохранит их в памяти .

Но, когда включена отложенная загрузка, если мы вытащим User Lazy , OrderDetail данные не будут инициализированы и загружены в память до тех пор, пока к ним не будет сделан явный вызов.

В следующем разделе мы увидим, как приведенный выше пример реализован в режиме гибернации.

4. Конфигурация Загрузки

В этом разделе мы рассмотрим, как мы можем настроить стратегии выборки в режиме гибернации. Мы будем повторно использовать примеры из предыдущего раздела.

Отложенную загрузку можно просто включить, используя следующий параметр аннотации:

fetch = FetchType.LAZY

Для использования нетерпеливой выборки используется следующий параметр:

fetch = FetchType.EAGER

Для настройки нетерпеливой загрузки мы использовали User Lazy двойной класс под названием User Eager .

В следующем разделе мы рассмотрим различия между двумя типами выборки.

5. Различия

Как мы уже упоминали, основное различие между двумя типами выборки заключается в моменте, когда данные загружаются в память.

Давайте взглянем на этот пример:

List users = sessionLazy.createQuery("From UserLazy").list();
UserLazy userLazyLoaded = users.get(3);
return (userLazyLoaded.getOrderDetail());

При использовании подхода ленивой инициализации Набор OrderDetail будет инициализирован только в том случае, если он явно вызывается с помощью геттера или какого-либо другого метода, как показано в приведенном выше примере:

UserLazy userLazyLoaded = users.get(3);

Но при активном подходе в Пользователь стремится он будет инициализирован немедленно в первой строке приведенного выше примера:

List user = sessionEager.createQuery("From UserEager").list();

Для ленивой загрузки используется прокси-объект и запускается отдельный SQL-запрос для загрузки набора OrderDetail .

Идея отключения прокси-серверов или ленивой загрузки считается плохой практикой в режиме гибернации. Это может привести к тому, что большое количество данных будет извлечено из базы данных и сохранено в памяти, независимо от необходимости в этом.

Для проверки вышеуказанной функциональности можно использовать следующий метод:

Hibernate.isInitialized(orderDetailSet);

Теперь важно взглянуть на запросы, которые генерируются в любом случае:

true

Приведенная выше настройка в fetching.hbm.xml показывает сгенерированные SQL-запросы. Если вы посмотрите на вывод консоли, то сможете увидеть сгенерированные запросы.

Для ленивой загрузки запроса, который создается для загрузки Пользовательских данных:

select user0_.USER_ID as USER_ID1_0_,  ... from USER user0_

Однако при быстрой загрузке мы увидели, что соединение выполняется с помощью USER_ORDER:

select orderdetai0_.USER_ID as USER_ID4_0_0_, orderdetai0_.ORDER_ID as ORDER_ID1_1_0_, orderdetai0_ ...
  from USER_ORDER orderdetai0_ where orderdetai0_.USER_ID=?

Приведенный выше запрос генерируется для всех Пользователей , что приводит к использованию гораздо большего объема памяти, чем при другом подходе.

6. Преимущества и недостатки

6.1. Ленивая загрузка

Преимущества:

  • Начальное время загрузки намного меньше, чем при другом подходе
  • Меньшее потребление памяти, чем при другом подходе

Недостатки:

  • Задержка инициализации может повлиять на производительность в нежелательные моменты
  • В некоторых случаях вам нужно обращаться с лениво инициализированными объектами с особой осторожностью, иначе вы можете получить исключение

6.2. Нетерпеливая Загрузка:

Преимущества:

  • Отсутствие влияния на производительность, связанного с задержкой инициализации

Недостатки:

  • Длительное начальное время загрузки
  • Загрузка слишком большого количества ненужных данных может повлиять на производительность

7. Ленивая загрузка в спящем режиме

Hibernate применяет подход с отложенной загрузкой к сущностям и ассоциациям, предоставляя прокси-реализацию классов.

Hibernate перехватывает вызовы сущности, заменяя ее прокси-сервером, производным от класса сущности. В нашем примере, когда запрашиваемая информация отсутствует, она будет загружена из базы данных до того, как управление будет передано реализации класса User .

Следует также отметить, что когда ассоциация представлена как класс коллекции (в приведенных выше примерах она представлена как Set orderDetailSet ), то создается оболочка и заменяется исходной коллекцией.

Чтобы узнать больше о шаблоне проектирования прокси-сервера, вы можете обратиться здесь .

8. Заключение

В этой статье мы показали примеры двух основных типов выборки, используемых в режиме гибернации.

Для получения знаний продвинутого уровня вы можете заглянуть на официальный сайт Hibernate. Чтобы получить код, обсуждаемый в этой статье, пожалуйста, загляните в этот репозиторий .