Итак, что вы имеете в виду, у вас есть Employee
, и у него есть отношение ~ ToMany (которое лениво выбирается) к FamilyMember
. У вас есть код, который перебирает всех членов семьи сотрудников, правильно?
т.е. как то так:
class Employee {
@OneToMany(fetch=LAZY)
List<FamilyMember> familyMembers;
}
и в вашем коде:
for (Employee employee: someEmployees) {
for (FamilyMember member: employee.getFamilyMembrs()) {
// do something
}
}
что-то подобное? (В вашем примере кода вы просто выбираете FamilyMember
, который не имеет ничего общего с отложенной выборкой)
Если это так, то Lazy Fetch НЕ собирается улучшать производительность.
Основная ситуация, в которой Lazy Fetch помогает в производительности, заключается в том, что отношения lazy-fetched не используются. Поэтому, когда Hibernate создает объект, он просто устанавливает в качестве отношения прокси-сервер, фактически не извлекая связанные объекты, тем самым сохраняя доступ к БД, передачу данных и построение объектов.
Однако в вашем случае вам необходимо получить доступ к отношениям, поэтому Hibernate не спасет вас от вышеуказанной работы. И, если ленивая выборка выполняется лениво, это означает, что ваша основная сущность будет сначала извлечена, а затем связь будет восстановлена, когда вы получите к ней доступ. Обычно это даже медленнее по сравнению с правильным соединением-выборкой для извлечения основного объекта + отношения одновременно.
Обновление: к вашему дополнительному вопросу о: как Hibernate справляется с такой ленивой загрузкой без предварительного запроса дочерних записей. Вот что происходит на высоком уровне:
Во-первых, hibernate по-разному работает с ленивой выборкой для разных типов отношений. В данном случае это OneToMany
отношение. Что знает Hibernate, основываясь на сопоставлении: @OneToMany List<FamilyMember> familyMembers;
это:
Таблица
FamilyMember
(сторона "to many") будет иметь столбец (предположим, по умолчанию он называется EmployeeId
), содержащий идентификатор текущей сущности (Employee
, сторона "one to") )
Следовательно, прокси-сервер lazy-fetch, который собирается создать Hibernate: прокси-сервер коллекции при обращении к нему запросит SQL select * from FamilyMember where EmployeeId = :id
, для которого :id
будет предоставлен идентификатор текущей сущности.
Таким образом, при создании Employee
вам не нужно запрашивать что-либо из его дочерних записей (FamilyMember
).
Когда вы, скажем, выполните employee.getFamilyMembers().get(2);
, метод .get(...)
запустит прокси-сервер сбора данных с отложенной выборкой, чтобы заполнить данные, что приведет к получению ВСЕХ связанных FamilyMember
записей (вместо только 3-й) и заполните коллекцию данными, а затем верните вам третий.
Чтобы понять поведение извлечения Hibernate, я бы посоветовал вам включить ведение журнала для SQL, выпущенного Hibernate (с помощью таких инструментов, как jdbcdslog или log4jdbc и т. Д.), И вы можете визуализировать, когда и что запрашивается Hibernate в ситуации.