Отношения OneToOne с общим первичным ключом генерируют n+1, выбирает; какое-либо обходное решение?

Хорошо, я сделал это, и это работает. Это в основном взломано вместе из разных ответов здесь. Поскольку в этой теме нет STILL неясного ответа, я решил опубликовать это.

<script type="text/javascript">
  $(document).ready(function () {
    $("#logo").hide();
    $("#logo").bind("load", function () { $(this).fadeIn(); });
  });
</script>

Мне кажется, это лучший способ сделать это. Несмотря на благие намерения Сони, он не упомянул, что сначала нужно настроить отображение объекта: ни один с помощью CSS. Проблема здесь в том, что если по какой-либо причине пользовательский JS не работает, объект просто никогда не появится. Нехорошо, особенно если это чертов логотип.

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

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

7
задан octy 16 June 2009 в 17:28
поделиться

5 ответов

Представьте 2 таблицы в реляционной базе данных, например Человек и биллинг. Между этими объектами определена (необязательная) ассоциация OneToOne

. Ленивая выборка концептуально невозможна для необязательной OneToOne по умолчанию, Hibernate должен обратиться к базе данных, чтобы узнать, является ли ассоциация нулевой ] или нет. Более подробная информация на этой старой странице вики:

Некоторые пояснения по отложенной загрузке (один к одному)

[...]

Теперь рассмотрим, что наш класс B имеет взаимно однозначная ассоциация с C

 классом B {
частный офис;

public C getCee () {
вернуть cee;
 }

public void setCee (C cee) {
this.cee = cee;
 }
}
class C {
 // На самом деле не важно
}

Сразу после загрузки B вы можете позвонить getCee () для получения C. Но посмотрите, getCee () - это метод ВАШЕГО класса и Hibernate не контролирует это. Hibernate не знает, когда кто-то вызовет getCee () . Тот означает, что Hibernate должен поставить соответствующее значение в " cee " свойство в момент загрузки B из база данных. Если прокси включен для C , Hibernate может поставить C-прокси объект, который еще не загружен, но будет загружен, когда кто-то его использует. Это дает ленивую загрузку для индивидуальный .

Но теперь представьте, что ваш объект B может или возможно, не связан C ( constrained = "false" ). Что должно getCee () возврат, когда конкретный B не имеет C ? Нулевой.Но помни, Hibernate должен установить правильное значение "cee" на данный момент установлено B (потому что он не знает, когда кто-то вызовет getCee () ). Прокси не помогите здесь, потому что прокси в уже ненулевой объект.

Итак, резюме: если ваше отображение B-> C является обязательным ( constrained = true ), Hibernate будет использовать прокси для C что приводит к отложенной инициализации. Но если вы разрешите B без C, Hibernate просто ДОЛЖЕН проверить наличие C в в момент загрузки B. Но SELECT для проверка присутствия просто неэффективна потому что тот же SELECT может не только проверить наличие, но загрузить всю объект. Так что ленивая загрузка уходит .

Итак, невозможно ... по умолчанию.

Есть ли способ обхода этой потенциальной катастрофы производительности (кроме отказа от использования общего первичного ключа)? Спасибо за все ваши идеи.

Проблема не в общем первичном ключе, с общим первичным ключом или без него, вы его получите, проблема в обнуляемом OneToOne.

Первый вариант : использовать инструментарий байт-кода (см. Ссылки на документацию ниже) и без прокси выборка:

@OneToOne( fetch = FetchType.LAZY )
@org.hibernate.annotations.LazyToOne(org.hibernate.annotations.LazyToOneOption.NO_PROXY)

Второй вариант : использовать поддельный ManyToOne (получить = FetchType.LAZY) . Это, наверное, самое простое решение (и, насколько мне известно, рекомендованное). Но я не тестировал это с общим ПК.

Третий вариант : Активная загрузка биллинга с помощью объединенной выборки .

Связанный вопрос

Ссылки

8
ответ дан 7 December 2019 в 03:19
поделиться

Вы можете попробовать «оптимизацию вслепую», которая хороша для «n + 1 задач выбора». Аннотируйте свое поле (или получатель) следующим образом:

@org.hibernate.annotations.BatchSize(size = 10)
java.util.Set<Billing> bills =  new HashSet<Billing>();
0
ответ дан 7 December 2019 в 03:19
поделиться

Это обычная проблема производительности Hibernate (просто выполните поиск по запросу «Hibernate n + 1»). Есть три способа избежать n + 1 запросов:

  • Размер пакета
  • Подвыбор
  • Выполните ЛЕВОЕ СОЕДИНЕНИЕ в своем запросе

Они описаны в часто задаваемых вопросах Hibernate здесь и ] здесь

1
ответ дан 7 December 2019 в 03:19
поделиться

Держитесь подальше от сопоставления OneToOne в спящем режиме

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

http://opensource.atlassian.com/projects/hibernate/browse/HHH-2128

0
ответ дан 7 December 2019 в 03:19
поделиться

Эта проблема "n + 1" возникнет только в том случае, если вы укажете отношение как ленивое или явно укажете, что хотите, чтобы спящий режим запускал отдельный запрос.

Hibernate может извлекать отношение к Billing с помощью внешнего соединения при выборе Person, что полностью устраняет проблему n + 1. Я думаю, что это указание fetch = "XXX" в ваших файлах hbm.

Ознакомьтесь с Кратким руководством по стратегиям извлечения

0
ответ дан 7 December 2019 в 03:19
поделиться
Другие вопросы по тегам:

Похожие вопросы: