2013-11-19 3 views
1

У меня есть два класса InvitedPerson и Flight с взаимной привязкой друг к другу. Вот как они аннотируются.Дополнительные запросы в JPA

public class InvitedTech{ 
    ... 
    @OneToOne(mappedBy="invitedTech", cascade = CascadeType.ALL, fetch=FetchType.LAZY) 
    public Flight flight; 

    @OneToOne(mappedBy="invitedTech", cascade = CascadeType.ALL, fetch=FetchType.LAZY) 
    public Hotel hotel; 

    ... 
} 

public class Flight{ 
    ... 
    @OneToOne 
    @JoinColumn(name="invitedTechId", nullable=false) 
    public InvitedTech invitedTech; 
    ... 
} 

Как вы можете видеть Flight является владельцем отношений и InvitedTech другая сторона этого двунаправленного отношения. InvitedTech также имеет отношение OneToOne с Hotel Теперь, когда я пишу простой запрос для получения всех рейсов, он вызывает три запроса в целом. 1-й, который дает мне результаты, но вызывает 2 дополнительных запроса.

List<Flight> flg = JPA.em().createQuery("SELECT flg from Flight flg").getResultList(); 
  1. запрос, который получает все рейсы (Это только один, что мне нужно)
  2. Запрос с объединением между InvitedTech и Flight
  3. Запрос с объединением между invitedTech и отель

Почему выполняется запрос 2 & 3, хотя я установил FetchType = Lazy. Я не имею доступа к информации о гостинице. И Flight не должны быть запросами снова, так как первый запрос возвращает данные.

После некоторых игр, когда я удаляю атрибут mappedBy из обоих аннотаций, эти 2 сложения не выполняются (то есть только 1-й выполняется).

Почему атрибут mappedBy вызывает выполнение дополнительных запросов, хотя FetchType=Lazy. Есть ли способ остановить это?

+0

Доступ к полям по-прежнему работает без атрибутов 'mappedBy'? – chrylis

+0

Если вы имеете в виду доступ к полям InvitedTech («Отель и рейс»), они будут иметь нулевое значение без сопоставления, поскольку JPA не знает об этом обратном отношении. – SpartanElite

ответ

2

Я считаю, что это связано с одной из идиосинкразии в Hibernate:

не опциональным один-к-одному отношения с готовностью загружены независимо от того, являются ли они отображаются в виде ленивых.

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

Я испытал это сам, и насколько я знаю, единственный путь вокруг него - отметить связь с необязательным = false, который сообщает Hibernate, что он всегда может установить прокси.

Если связь является необязательной, то единственным вариантом является, по-видимому, байт-код.

Смотрите также:

https://community.jboss.org/wiki/SomeExplanationsOnLazyLoadingone-to-one

Making a OneToOne-relation lazy

+0

Где вы устанавливаете optional = false? –

+0

http://docs.oracle.com/javaee/5/api/javax/persistence/OneToOne.html –

0

Вы не установили связь с рейса на InvitedTech ленивым. Поэтому он загружает InvitedTech, связанный с полетом.

Поскольку он не может узнать из InvitedTech, если существует отель и рейс, связанный с InvitedTech, он не может решить, должны ли эти поля быть нулевыми или должны быть прокси. Поэтому он вынужден выполнять дополнительные запросы, чтобы узнать, существует ли отель/рейс для InvitedTech.

+0

Я намеренно установил Flight to inviteTech как не ленивый, так как хотел бы получить приглашенные детали о доступе к рейсу. Почему он выполняет дополнительный запрос для полета, несмотря на то, что предыдущий запрос запрашивает приглашениеTech? Также есть способ остановить выполнение этих двух запросов до тех пор, пока они не будут доступны? – SpartanElite

+0

Если ассоциация не является необязательной, отметьте ее так. В противном случае, IIRC, вы можете задействовать свои объекты во время компиляции и аннотировать связь с LazyToOne (NO_PROXY), но у меня был плохой опыт с этим ранее. Возможно, сейчас все работает нормально. –

Смежные вопросы