Я новичок в Java Persistence API и Hibernate.
В чем разница между FetchType.LAZY
и FetchType.EAGER
в Java Persistence API?
Я новичок в Java Persistence API и Hibernate.
В чем разница между FetchType.LAZY
и FetchType.EAGER
в Java Persistence API?
Ответы:
Иногда у вас есть две сущности, и между ними есть отношения. Например, у вас может быть названная сущность
University
и другая сущность,Student
а в университете может быть много студентов:Сущность университета может иметь некоторые базовые свойства, такие как идентификатор, имя, адрес и т. Д., А также свойство коллекции, называемое студенты, которое возвращает список студентов для данного университета:
Теперь, когда вы загружаете университет из базы данных, JPA загружает его поля id, name и address. Но у вас есть два варианта загрузки студентов:
getStudents()
.Когда в университете много студентов, неэффективно загружать всех своих студентов вместе с ним, особенно когда они не нужны, и в подобных случаях вы можете заявить, что хотите, чтобы студенты загружались, когда они действительно необходимы. Это называется отложенной загрузкой.
Вот пример, где
students
явно помечены для быстрой загрузки:И вот пример, где
students
явно помечен для ленивой загрузки:источник
getStudents()
), но иногда это невозможно, потому что к тому времени этот метод вызывается, сеанс уже закрыт и сущность отсоединена. Точно так же иногда мы имеем архитектуру клиент / сервер (например, клиент Swing / сервер JEE), и сущности / DTO передаются клиенту по проводам, и опять же чаще всего в этих сценариях отложенная загрузка не будет работать из-за способа, которым сущности сериализуются по проводу.getStudents()
метод в первый раз, кэшируются ли результаты? чтобы в следующий раз я мог быстрее получить доступ к этим результатам?В принципе,
источник
EAGER
загрузка коллекций означает, что они извлекаются полностью во время извлечения их родителя. Так что, если у вас естьCourse
и естьList<Student>
, все студенты выбираются из базы данных в то время, когда ониCourse
выбираются.LAZY
с другой стороны, означает, что содержимоеList
выбирается только при попытке доступа к ним. Например, по телефонуcourse.getStudents().iterator()
. Вызов любого метода доступа дляList
инициатора вызовет базу данных для получения элементов. Это реализуется путем создания прокси вокругList
(илиSet
). Так что для ваших ленивых коллекций конкретных типов нетArrayList
иHashSet
, ноPersistentSet
иPersistentList
(илиPersistentBag
)источник
course.getStudents()
, он запускает SQL-запрос (видел это на консоли). В типе Lazy fetch тоже самое происходит. Так в чем же разница?fetchtype = LAZY
умолчанию, даже если попытаться получить коллекцию с помощью getter, hibernete выдает ошибку, сообщающую, что не может оценитьЯ могу рассмотреть производительность и использование памяти. Одно большое отличие состоит в том, что стратегия извлечения EAGER позволяет использовать извлеченный объект данных без сеанса. Почему?
Все данные извлекаются, когда стремятся отметить данные в объекте, когда сеанс подключен. Однако, в случае стратегии отложенной загрузки, отложенная загрузка помеченного объекта не извлекает данные, если сеанс отключен (после
session.close()
оператора). Все это можно сделать с помощью Hibernate-прокси. Стремительная стратегия позволяет данным оставаться доступными после закрытия сессии.источник
Насколько мне известно, оба типа выборки зависит от ваших требований.
FetchType.LAZY
по требованию (то есть, когда нам потребовались данные).FetchType.EAGER
немедленно (т.е. до того, как наше требование наступит, мы без необходимости извлекаем запись)источник
По умолчанию для всех объектов коллекции и карты применяется правило выборки,
FetchType.LAZY
а для других экземпляров оно соответствуетFetchType.EAGER
политике.Вкратце,
@OneToMany
и@ManyToMany
отношения не извлекают связанные объекты (сбор и отображение) неявным образом, но операция поиска осуществляется каскадно через поле в@OneToOne
и@ManyToOne
единицах.(любезно предоставлено: - objectdbcom)
источник
Оба
FetchType.LAZY
иFetchType.EAGER
используются для определения плана выборки по умолчанию .К сожалению, вы можете переопределить план выборки по умолчанию только для LAZY. Извлечение EAGER менее гибко и может привести ко многим проблемам с производительностью .
Мой совет заключается в том, чтобы ограничить желание сделать ваши ассоциации EAGER, потому что выборка - это вопрос времени. Поэтому все ваши запросы должны использовать директиву fetch, чтобы получить только то, что необходимо для текущего бизнес-кейса.
источник
Из Javadoc :
Например, жаждущий активнее, чем ленивый. Ленивый происходит только при первом использовании (если провайдер берет подсказку), тогда как с нетерпением (может) получать заранее.
источник
Тип
Lazy
Fetch по умолчанию выбирается Hibernate, если вы явно не отметилиEager
тип Fetch. Чтобы быть более точным и кратким, различие может быть заявлено как ниже.FetchType.LAZY
= Это не загружает отношения, если вы не вызываете их через метод getter.FetchType.EAGER
= Это загружает все отношения.Плюсы и минусы этих двух типов извлечения.
Lazy initialization
повышает производительность, избегая ненужных вычислений и уменьшая требования к памяти.Eager initialization
занимает больше памяти и скорость обработки медленная.Сказав это, в зависимости от ситуации можно использовать любую из этих инициализаций.
источник
getMember
вызываемая функция, которая точно соответствует шаблону имени члена?Book.java
Subject.java
HibernateUtil.java
Main.java
Проверьте метод retrieve () файла Main.java. Когда мы получим Subject, его коллекция listBooks , снабженная комментариями
@OneToMany
, будет загружаться лениво. Но, с другой стороны, связанное с Книгой объединение предмета коллекции , снабженное комментариями@ManyToOne
, загружается раньше ([default][1]
для@ManyToOne
,fetchType=EAGER
). Мы можем изменить поведение, поместив fetchType.EAGER в@OneToMany
Subject.java или fetchType.LAZY@ManyToOne
в Books.java.источник
Источник
источник
Я хочу добавить эту заметку к тому, что сказал «Кён Хван Мин» выше.
Предположим, вы используете Spring Rest с этим простым архитектором:
И вы хотите вернуть некоторые данные во
FetchType.LAZY
внешний интерфейс, если вы используете , вы получите исключение после того, как вернете данные в метод контроллера, так как сеанс закрыт в Сервисе, поэтомуJSON Mapper Object
невозможно получить данные.Существует три распространенных варианта решения этой проблемы, в зависимости от дизайна, производительности и разработчика:
FetchType.EAGER
, так что сеанс будет все еще жив при методе контроллера.FetchType.LAZY
метод преобразователя для передачи данныхEntity
в другой объект данныхDTO
и отправки их в контроллер, поэтому не исключение, если сеанс закрыт.источник
Привет, я приложил 2 фотографии, чтобы помочь вам понять это.
источник
@ drop-shadow, если вы используете Hibernate, вы можете вызвать,
Hibernate.initialize()
когда вызываетеgetStudents()
метод:источник
LAZY: он лениво выбирает дочерние сущности, т.е. во время выборки родительской сущности, он просто выбирает прокси (созданный cglib или любой другой утилитой) дочерних сущностей, и когда вы получаете доступ к любому свойству дочерней сущности, он фактически извлекается hibernate.
EAGER: он выбирает дочерние объекты вместе с родительскими.
Для лучшего понимания перейдите к документации Jboss или вы можете использовать
hibernate.show_sql=true
для своего приложения и проверить запросы, выданные hibernate.источник