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

178

Что такое ленивая загрузка в Java? Я не понимаю процесс. Кто-нибудь может помочь мне понять процесс отложенной загрузки?

коромысло
источник

Ответы:

268

Скажем, у вас есть родитель, и у этого родителя есть коллекция детей. Hibernate теперь может «лениво загружать» дочерние элементы, что означает, что он фактически не загружает все дочерние элементы при загрузке родительского элемента. Вместо этого он загружает их по запросу. Вы можете запросить это явно или, что гораздо чаще, hibernate будет загружать их автоматически при попытке доступа к дочернему элементу.

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

Также остерегайтесь проблемы n + 1. Hibernate не будет загружать все дочерние элементы при доступе к коллекции. Вместо этого он загрузит каждого ребенка в отдельности. При выполнении итерации по коллекции это вызывает запрос для каждого дочернего элемента. Чтобы избежать этого, вы можете обмануть hibernate для загрузки всех дочерних элементов одновременно, например, вызвав parent.getChildren (). Size ().

Томас Лётцер
источник
5
В качестве альтернативы следует использовать Hibernate.initialize (parent.getChildren ())
HakunaMatata
18
Утверждение «когда вы получаете доступ к коллекции ... она загружает каждого потомка индивидуально» на самом деле совершенно неточно. На самом деле это полная противоположность. Любая разыменование parent.getChildren () приведет к тому, что Hibernate загрузит все дочерние элементы в коллекции в одном запросе БД. Если только вы не воспользовались очень специальной подсказкой для «ленивой загрузки». Или, если вы не кэшируете коллекцию в кэше второго уровня, и связанные дочерние элементы также не кэшируются.
Стив Эберсоле
О, переполнение стека - лучший ответ можно найти внизу страницы ;-)
Пиотрек Гричук
76

Означает «ленивая загрузка» , что объект будет загружен только если вы на самом деле обращается к сущности для первого времени.

Картина выглядит так:

public Entity getEntity() {
    if (entity == null) {
        entity = loadEntity();
    }
    return entity;
}

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

В Hibernate вы можете настроить ленивую загрузку коллекции дочерних объектов. Затем фактическая отложенная загрузка выполняется внутри методов, PersistentSetкоторые Hibernate использует «под капотами» для назначения коллекции объектов как Set.

Например

public class Parent {
    private Set<Child> children;

    public Set<Child> getChildren() {
        return children;
    }
}

,

public void doSomething() {
    Set<Child> children = parent.getChildren(); // Still contains nothing.

    // Whenever you call one of the following (indirectly), 
    // Hibernate will start to actually load and fill the set.
    children.size();
    children.iterator();
}
BalusC
источник
25

Мартин Фаулер определяет шаблон отложенной загрузки в шаблонах архитектуры корпоративных приложений следующим образом:

Объект, который не содержит всех необходимых вам данных, но знает, как их получить.

Таким образом, при загрузке данного объекта идея состоит в том, чтобы не пытаться загружать связанные объекты, которые вы не можете использовать немедленно, чтобы сэкономить связанные с этим затраты производительности. Вместо этого связанный объект (ы) будет загружен только при использовании.

Это не шаблон, специфичный для доступа к данным и Hibernate, но он особенно полезен в таких областях, и Hibernate поддерживает ленивую загрузку ассоциаций «один ко многим» и ассоциаций «один к одному» и «многие к одному». при определенных условиях. Ленивое взаимодействие обсуждается более подробно в Главе 19 Справочной документации по Hibernate 3.0.

Паскаль Тивент
источник
15

По умолчанию отложенная загрузка имеет значение true. Ленивая загрузка означает, что при выполнении запроса select он не попадет в базу данных. Он будет ожидать функцию получения, то есть когда нам потребуется, он будет извлекать данные из базы данных. Например: Вы - родитель, у которого есть ребенок с большим количеством игрушек. Но текущая проблема в том, что когда бы ты ни позвонил ему (мы предполагаем, что у тебя есть мальчик), он приходит к тебе со всеми своими игрушками. Теперь это проблема, так как вы не хотите, чтобы он все время носил свои игрушки. Таким образом, будучи обоснованным родителем, вы идете вперед и определяете игрушки ребенка как ленивые. Теперь, когда вы звоните ему, он приходит к вам без игрушек.

Чандреш Соланки
источник
11

Ленивое извлечение решает, загружать ли дочерние объекты при загрузке родительского объекта. Вы должны сделать эту настройку соответствующего файла отображения hibernate родительского класса. Lazy = true(означает не загружать дочерние элементы). По умолчанию отложенная загрузка дочерних объектов имеет значение true.

Это гарантирует, что дочерние объекты не загружаются, если они явно не вызваны в приложении путем вызова getChild()метода для parent. В этом случае hibernate выдает новый вызов базы данных, чтобы загрузить дочерний getChild()объект, когда он фактически вызывается для родительского объекта.

Но в некоторых случаях вам нужно загрузить дочерние объекты, когда родительский загружен. Просто сделайте lazy = false, и hibernate загрузит дочерний элемент при загрузке parent из базы данных.

Пример: если у вас есть СТОЛ? EMPLOYEE отображается на объект Employee и содержит набор объектов Address. Родительский класс: класс сотрудников, дочерний класс: адресный класс

public class Employee { 
private Set address = new HashSet(); // contains set of child Address objects 
public Set getAddress () { 
return address; 
} 
public void setAddresss(Set address) { 
this. address = address; 
} 
} 

В файле Employee.hbm.xml

<set name="address" inverse="true" cascade="delete" lazy="false"> 
<key column="a_id" /> 
<one-to-many class="beans Address"/> 
</set> 

В приведенной конфигурации. Если lazy="false": - при загрузке объекта Employee в это время также загружается дочерний объект Address и устанавливается метод setAddresss (). Если вы вызываете employee.getAdress (), то загруженные данные возвращаются. Нет нового вызова базы данных.

Если lazy="true": - это конфигурация по умолчанию. Если вы не упомянули, то в спящем режиме считайте lazy = true. при загрузке объекта Employee дочерний объект Adress того времени не загружается. Вам нужен дополнительный вызов к базе данных, чтобы получить адресные объекты. Если вы позвоните, employee.getAdress()то запрос времени базы данных сработает и вернет результаты. Свежий вызов базы данных.

Бхавин шах
источник
Сотрудник и Адрес не имеют отношения Родитель-ребенок в этом сценарии. Это отношения "есть" !
Рам
Это агрегация, а не наследование.
Риши
11

На языке непрофессионала, это как будто вы делаете торт, и вам понадобится 5-10 ингредиентов из холодильника. У вас есть два варианта: взять все ингредиенты из холодильника и поставить их на кухонную платформу, или принести предмет, который вам нужен, когда вам нужно.

Точно так же при активной загрузке вы извлекаете всю информацию о бобе и связанных с ним классах (не дочерних или не-связанных, но имеющих отношение, то есть в торте есть мука, есть молоко, есть сливки и т. Д.), А в случае отложенной загрузки сначала Вы приносите только его идентификатор и значения, которые приходят из той же таблицы (необходимые ингредиенты, которые вам сначала понадобятся в вашей миске в случае торта). Вся информация, поступающая из других таблиц, будет выбираться по мере необходимости / при необходимости.

Keyur
источник
8

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

Штеффен
источник
4

Ленивая загрузка позволяет вам отложить поиск ассоциации или лучше контролировать стратегию извлечения.

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

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

Влад Михалча
источник
3

Параметр Lazy решает, следует ли загружать дочерние объекты при загрузке родительского объекта. Вам необходимо сделать этот параметр соответствующим файлом отображения гибернации родительского класса. Lazy = true (означает не загружать дочерние объекты). По умолчанию отложенная загрузка дочерних объектов имеет значение true. , Это гарантирует, что дочерние объекты не загружаются, если они явно не вызваны в приложении путем вызова метода getChild () для parent. В этом случае hibernate выдает новый вызов базы данных, чтобы загрузить дочерний объект, когда getChild () фактически вызывается для Parent object.But в некоторых случаях вам нужно загрузить дочерние объекты при загрузке parent. Просто сделайте lazy = false, и hibernate загрузит дочерний элемент при загрузке parent из базы данных. Exampleslazy = true (по умолчанию). Дочерний адрес класса User можно сделать ленивым, если он не требуется часто.

Шива Чимпири
источник
2

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

Википедия

Ссылка Ленивая Загрузка с hibernate.org

Диего Диас
источник
1

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

Абхинай Пандей
источник
0

Hiberante поддерживает функцию отложенной инициализации как для сущностей, так и для коллекций. Движок Hibernate загружает только те объекты, которые мы запрашиваем, но не другие объекты или коллекции.

lazy = "false" по умолчанию при загрузке упоминание об инициализации для единственного дочернего элемента - lazy.in true, если родительский объект загрузки не поддерживает дочерний элемент

abburi
источник
0

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

Manikandan Adhimoolam
источник
0

Удивительно, но ни один из ответов не говорит о том, как это достигается спящим режимом за экранами.

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


1. Инструментарий байт-кода :

Расширяет определение базового класса с помощью ловушек hibernate для перехвата всех вызовов этого объекта.

Сделано либо во время компиляции, либо во время загрузки [load]

1.1 Время компиляции

  • Операция после компиляции

  • В основном плагинами maven / ant

1.2 Время выполнения

  • Если инструментарий во время компиляции не выполняется, он создается во время выполнения с использованием таких библиотек, как javassist

2. Прокси

Объект-сущность, возвращаемый Hibernate, является прокси реального типа.

Смотрите также: Javassist. Какова основная идея и где реальное использование?

Санкарганеш Ишваран
источник