Тип выборки по умолчанию для один-к-одному, многие-к-одному и один-ко-многим в Hibernate

104

Каков тип выборки по умолчанию в сопоставлениях гибернации?

После исследования я узнал следующее:

  • один на один очень хочет .
  • для одного ко многим это лениво .

Но после тестирования в Eclipse, все захотели.

Это зависит от того, использую ли я JPA или Hibernate?

Richa
источник
1
Если вы все еще занимаетесь темами JPA - я обновил ваш вопрос новым ответом, так как старые устарели для текущей версии Hibernate.
Александр Рюль

Ответы:

194

Это зависит от того, используете ли вы JPA или Hibernate.

Из спецификации JPA 2.0 , значения по умолчанию:

OneToMany: LAZY
ManyToOne: EAGER
ManyToMany: LAZY
OneToOne: EAGER

А в спячке все лениво

ОБНОВИТЬ:

Последняя версия Hibernate соответствует указанным выше значениям JPA по умолчанию.

Ашиш Агарвал
источник
11
«А в спящем режиме все лениво», видимо, изменилось в последних версиях. См . Ответ Александра Рюля ниже .
Dinei
1
Hibernate - одна из реализаций JPA, поэтому, когда вы используете Hibernate, вы используете JPA :)
xenteros
Это популярный запрос. @ Ашиш Агарвал Не могли бы вы обновить последнюю строку вашего ответа. В Hibernate теперь не ленивый.
Саураб Тивари
Обновлен пост в отношении последнего поведения Hibernate.
M Anouti
Было обновление, в котором утверждалось, что нетерпеливый - это тип выборки по умолчанию для каждого сопоставления, что опровергается главой 11.3 как в текущей документации Hibernate 5.x, так и в новой документации 6.x, поэтому я отменил правку. Кроме того, рекомендуется не использовать автоматическое рвение, поскольку это, вероятно, означало бы выбор всей базы данных при выборке одного объекта.
Александр Рюль
52

Я знаю, что ответы были правильными на момент, когда задавался вопрос, но поскольку люди (такие как я в эту минуту) все еще находят, что им интересно, почему их WildFly 10 ведет себя по-другому, я хотел бы дать обновление для текущего Hibernate 5 .x версия:

В Руководстве пользователя Hibernate 5.2 это указано в главе 11.2. Применение стратегий выборки :

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

Таким образом, Hibernate также ведет себя как Ашиш Агарвал, указанный выше для JPA:

OneToMany: LAZY
ManyToOne: EAGER
ManyToMany: LAZY
OneToOne: EAGER

(см. спецификацию JPA 2.1 )

Александр Рюль
источник
А что, если мы используем собственный спящий режим вместо JPA impl, будет ли он действовать таким же образом?
jMounir 02
@jMounir: Ну, я этого не пробовал, но поскольку Hibernate утверждает, что он ведет себя так, как определено в JPA, я не понимаю, почему это будет отличаться при использовании Hibernate для себя. В обоих случаях можно изменить стратегию по умолчанию.
Александр Рюль
15

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

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

Таким образом, Hibernate всегда будет загружать любой объект, используя стратегию отложенной выборки, независимо от того, какой тип отношений вы объявили. Он будет использовать ленивый прокси (который должен быть неинициализированным, но не нулевым) для одного объекта в отношении один-к-одному или многие-к-одному, а также нулевую коллекцию, которая будет заполнена значениями при попытке доступа к ней. .

Следует понимать, что Hibernate будет пытаться заполнить эти объекты значениями только тогда, когда вы попытаетесь получить доступ к объекту, если вы не укажете fetchType.EAGER.

JamesENL
источник
0

Для однозначных ассоциаций, т. Е. «Один-к-одному» и «Многие-к-одному»: -
По умолчанию Lazy = прокси.
Ленивая загрузка прокси : - Это означает, что загружен прокси-объект вашей связанной сущности. Это означает, что для прокси-объекта связанной сущности загружается только идентификатор, соединяющий две сущности.
Например: A и B - это две сущности с ассоциацией "многие к одному". то есть: Там может быть мультипликатора для каждого B. Каждый объект A будет содержать ссылку на B.
`

public class A{
    int aid;
    //some other A parameters;
    B b;
}
public class B{
    int bid;
     //some other B parameters;
}

`
Отношение A будет содержать столбцы (помощь, ставка, ... другие столбцы объекта A).
Отношение B будет содержать столбцы (ставка, ... другие столбцы объекта B).

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

Для коллекций, то есть «многие-ко-многим» и «один-ко-многим»: -
По умолчанию Lazy = true


Обратите внимание, что стратегия выборки (выбор, присоединение и т. Д.) Может отменять ленивость. то есть: если lazy = 'true' и fetch = 'join', выборка A также приведет к выборке B или B (в случае коллекций). Вы можете понять причину, если задумаетесь.
Выборка по умолчанию для однозначной ассоциации - «соединение».
Выборка по умолчанию для коллекций - «select». Пожалуйста, проверьте последние две строки. Я пришел к логическому выводу.

Джиджо Мэтью
источник