Прежде всего, некоторые пояснения к ответу KLE :
Неограниченная (обнуляемая) взаимно-однозначная ассоциация является единственной, которую нельзя проксировать без инструментирования байт-кодом. Причина этого заключается в том, что объект-владелец ДОЛЖЕН знать, должно ли свойство ассоциации содержать прокси-объект или NULL, и он не может определить это, просматривая столбцы своей базовой таблицы из-за того, что один-к-одному обычно сопоставляют через общий PK, поэтому в любом случае должен быть извлечен с нетерпением, делая прокси бессмысленным. Вот более подробное объяснение.
ассоциации многие-к-одному (и, очевидно, один-ко-многим) не страдают от этой проблемы. Субъект-владелец может легко проверить свой собственный FK (и в случае «один ко многим» пустой прокси-сервер коллекции создается изначально и заполняется по требованию), поэтому сопоставление может быть ленивым.
Замена один-к-одному на один-ко-многим никогда не бывает хорошей идеей. Вы можете заменить его уникальным много-к-одному, но есть и другие (возможно, лучшие) варианты.
Роб Х. имеет действительную точку, однако , вы не можете быть в состоянии осуществить это в зависимости от модели (например , если ваш один-к-одному ассоциации является обнуляемым).
Теперь, что касается оригинального вопроса:
А) @ManyToOne(fetch=FetchType.LAZY)
должно работать просто отлично. Вы уверены, что он не перезаписывается в самом запросе? Можно указать join fetch
в HQL и / или явно установить режим выборки через Criteria API, который будет иметь приоритет над аннотацией класса. Если это не так, и у вас все еще есть проблемы, пожалуйста, опубликуйте ваши классы, запрос и полученный SQL для более подробного обсуждения.
Б) @OneToOne
хитрее. Если это определенно не обнуляемо, воспользуйтесь предложением Роба Х. и укажите его так:
@OneToOne(optional = false, fetch = FetchType.LAZY)
В противном случае, если вы можете изменить свою базу данных (добавить столбец внешнего ключа в таблицу владельцев), сделайте это и сопоставьте ее как «присоединенную»:
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name="other_entity_fk")
public OtherEntity getOther()
и в OtherEntity:
@OneToOne(mappedBy = "other")
public OwnerEntity getOwner()
Если вы не можете этого сделать (и не можете жить с нетерпеливым извлечением), байт-код - ваш единственный выбор. Я должен согласиться с CPerkins , однако - если у вас есть 80 !!! присоединяется из-за активных ассоциаций OneToOne, у вас есть большие проблемы, чем это :-)
one-to-one
с формулой, какselect other_entity.id from other_entity where id = other_entity.id
. Конечно, это не идеально для выполнения запросов.Чтобы ленивая загрузка работала с взаимно однозначными сопоставлениями, вам нужно позволить hibernate делать инструментарий времени компиляции и добавлять отношение
@LazyToOne(value = LazyToOneOption.NO_PROXY)
«один к одному».Пример сопоставления:
Пример расширения файла Ant Build (для инструментария Hibernate во время компиляции):
источник
LazyToOneOption.NO_PROXY
и нетLazyToOneOption.PROXY
?Основная идея XToOnes в Hibernate заключается в том, что в большинстве случаев они не ленивы.
Одна из причин заключается в том, что, когда Hibernate должен решить поставить прокси-сервер (с идентификатором) или ноль,
он все равно должен заглянуть в другую таблицу. чтобы присоединиться. Стоимость доступа к другой таблице в базе данных значительна, поэтому она может также извлечь данные для этой таблицы в этот момент (не ленивое поведение) вместо того, чтобы извлекать их в более позднем запросе, который потребует второго доступа к та же таблица.
Отредактировано: подробности см. В ответе ChssPly76 . Этот менее точный и подробный, ему нечего предложить. Спасибо ChssPly76.
источник
Вот кое-что, что работает для меня (без инструментов):
Вместо того, чтобы использовать
@OneToOne
с обеих сторон, я использую@OneToMany
в обратной части отношения (ту, с которойmappedBy
). Это делает свойство коллекцией (List
в примере ниже), но я перевожу его в элемент в получателе, делая его прозрачным для клиентов.Эта настройка работает лениво, то есть выбор производится только при вызове
getPrevious()
илиgetNext()
вызове - и только один выбор для каждого вызова.Структура таблицы:
Класс:
источник
Как я объяснил в этой статье , если вы не используете улучшение байт-кода , вы не можете лениво извлекать родительскую сторону
@OneToOne
ассоциацию .Однако, чаще всего вам даже не нужна родительская ассоциация, если вы используете
@MapsId
на стороне клиента:С
@MapsId
, тоid
свойство в дочерней таблице служит как Первичным ключом, так и Внешним ключом для родительской таблицы Первичный ключ.Итак, если у вас есть ссылка на родительский
Post
объект, вы можете легко получить дочерний объект, используя идентификатор родительского объекта:Таким образом, у вас не будет проблем с N + 1 запросами, которые могут быть вызваны
mappedBy
@OneToOne
связью на родительской стороне.источник
В нативных XML-сопоставлениях Hibernate этого можно добиться, объявив сопоставление « один к одному» с установленным для true ограниченным атрибутом. Я не уверен, что такое эквивалент аннотации Hibernate / JPA, и быстрый поиск документа не дал ответа, но, надеюсь, это даст вам возможность продолжить.
источник
@OneToOne(optional=false,fetch=FetchMode.LAZY)
Как уже прекрасно объясняется ChssPly76, проксите в Hibernate не помогают (безусловным обнуляемым) ассоциацию один-к-одному, НО есть трюк объяснил здесь , чтобы избежать , чтобы настроить аппаратуру. Идея состоит в том, чтобы обмануть Hibernate, так как класс сущностей, который мы хотим использовать, уже инструментирован: вы вручную вводите его в исходный код. Это просто! Я реализовал его с CGLib в качестве поставщика байт-кода, и он работает (убедитесь, что вы настроили lazy = "no-proxy" и fetch = "select", а не "join", в вашем HBM).
Я думаю, что это хорошая альтернатива реальным (я имею в виду, автоматическим) инструментальным средствам, когда у вас есть только одно однозначное отношение, которое вы хотите сделать ленивым. Основным недостатком является то, что решение зависит от поставщика байт-кода, который вы используете, поэтому прокомментируйте свой класс точно, потому что в будущем вам, возможно, придется сменить поставщика байт-кода; Конечно, вы также модифицируете свой компонент по технической причине, и это не хорошо.
источник
Этот вопрос довольно старый, но в Hibernate 5.1.10 есть новое, более удобное решение.
Ленивая загрузка работает за исключением родительской стороны ассоциации @OneToOne. Это связано с тем, что в Hibernate нет другого способа узнать, назначать ли этой переменной нуль или прокси. Более подробную информацию вы можете найти в этой статье
источник
Если отношение не должно быть двунаправленным, то @ElementCollection может быть проще, чем использование ленивой коллекции One2Many.
источник