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 SetorderDetail = 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. Различия
Как мы уже упоминали, основное различие между двумя типами выборки заключается в моменте, когда данные загружаются в память.
Давайте взглянем на этот пример:
Listusers = sessionLazy.createQuery("From UserLazy").list(); UserLazy userLazyLoaded = users.get(3); return (userLazyLoaded.getOrderDetail());
При использовании подхода ленивой инициализации Набор OrderDetail будет инициализирован только в том случае, если он явно вызывается с помощью геттера или какого-либо другого метода, как показано в приведенном выше примере:
UserLazy userLazyLoaded = users.get(3);
Но при активном подходе в Пользователь стремится он будет инициализирован немедленно в первой строке приведенного выше примера:
Listuser = 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. Чтобы получить код, обсуждаемый в этой статье, пожалуйста, загляните в этот репозиторий .