Вопрос по java – Отношение OneToOne с общим первичным ключом генерирует n + 1 выбор; любой обходной путь?

7

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

Когда вы выбираете Person с помощью именованного запроса, такого как:

from Person p where p.id = :id

Hibernate / JPA генерирует два запроса на выборку: один для таблицы Person, а другой для таблицы Billing.

Приведенный выше пример очень прост и не вызовет проблем с производительностью, поскольку запрос возвращает только один результат. Теперь представьте, чтоPerson имеетn Отношения OneToOne (все не обязательно) с другими объектами (все разделяютPerson основной ключ).

Поправьте меня, если я ошибаюсь, ноselect запрос на человека, возвращаяr строки, приведет к(n+1)*r выбирает сгенерированный Hibernate, даже если ассоциацииlazy.

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

Error: User Rate Limit Exceeded Stefan Mai
Error: User Rate Limit Exceeded skaffman
Error: User Rate Limit Exceeded octy
Error: User Rate Limit Exceededstackoverflow.com/questions/463349 Steve Kuo
Error: User Rate Limit Exceeded skaffman

Ваш Ответ

5   ответов
1

Error: User Rate Limit Exceeded

  • Batch size
  • Subselect
  • Do a LEFT JOIN in your query

Error: User Rate Limit ExceededError: User Rate Limit ExceededError: User Rate Limit ExceededError: User Rate Limit Exceeded

0

Stay away from hibernate's OneToOne mapping

Error: User Rate Limit Exceeded

Error: User Rate Limit Exceeded

HHH-2128Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
8

e.g. Person and Billing. There is a (non-mandatory) OneToOne association defined between these entities,

Error: User Rate Limit ExceedednullError: User Rate Limit Exceeded

Some explanations on lazy loading (one-to-one)

[...]

Now consider our class B has one-to-one association to C

class B {
    private C cee;

    public C getCee() {
        return cee;
    }

    public void setCee(C cee) {
        this.cee = cee;
    }
}

class C {
    // Not important really
}

Right after loading B, you may call getCee() to obtain C. But look, getCee() is a method of YOUR class and Hibernate has no control over it. Hibernate does not know when someone is going to call getCee(). That means Hibernate must put an appropriate value into "cee" property at the moment it loads B from database. If proxy is enabled for C, Hibernate can put a C-proxy object which is not loaded yet, but will be loaded when someone uses it. This gives lazy loading for one-to-one.

But now imagine your B object may or may not have associated C (constrained="false"). What should getCee() return when specific B does not have C? Null. But remember, Hibernate must set correct value of "cee" at the moment it set B (because it does no know when someone will call getCee()). Proxy does not help here because proxy itself in already non-null object.

So the resume: if your B->C mapping is mandatory (constrained=true), Hibernate will use proxy for C resulting in lazy initialization. But if you allow B without C, Hibernate just HAS TO check presence of C at the moment it loads B. But a SELECT to check presence is just inefficient because the same SELECT may not just check presence, but load entire object. So lazy loading goes away.

Error: User Rate Limit Exceeded

Is there a workaround for this potential performance disaster (other than not using a shared primary key at all)? Thank you for all your ideas.

Error: User Rate Limit ExceedednullableError: User Rate Limit Exceeded

First optionError: User Rate Limit Exceededno-proxyError: User Rate Limit Exceeded

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

Second optionError: User Rate Limit ExceededManyToOne(fetch=FetchType.LAZY)Error: User Rate Limit Exceeded

Third optionError: User Rate Limit Exceededjoin fetch.

Related question Making a OneToOne-relation lazy References Hibernate Reference Guide 19.1.3. Single-ended association proxies 19.1.7. Using lazy property fetching Old Hibernate FAQ How do I set up a 1-to-1 relationship as lazy? Hibernate Wiki Some explanations on lazy loading (one-to-one)
Error: User Rate Limit Exceeded octy
0

@org.hibernate.annotations.BatchSize(size = 10)
java.util.Set<Billing> bills =  new HashSet<Billing>();
0

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