2012-01-25 2 views
13

Существует класс Offer, который имеет факультативно отношение к классу Article. Так что некоторые свойства статьи содержат значение null.Hibernate/JPA: Как заставить неявные соединения использовать LEFT OUTER JOINS

Если я использую следующее заявление, все работает нормально. У меня есть все предложения, даже те, у которых нет статьи.

SELECT o FROM Offer o 
     LEFT OUTER JOIN o.article a 
     LEFT OUTER JOIN o.vendor v 
     WHERE v.number = '0212' OR a.nummer = '123456' 

Если я изменяю заявление:

SELECT o FROM Offer o 
     LEFT OUTER JOIN o.article a 
     LEFT OUTER JOIN o.vendor v 
     WHERE v.number = '0212' OR o.article.nummer = '123456' 

я получил только эти предложения, имеющие статьи, отличные от NULL. Это связано с тем, что обозначение для неявных соединений (o.article.nummer) вызывает внутреннее соединение.

Есть ли возможность принудительно включить левые внешние соединения в неявные объединения (аннотация управляется или что-то еще)? Если есть шанс, что я мог бы использовать короткую форму, как это:

SELECT o FROM Offer o 
     WHERE v.number = '0212' OR o.article.nummer = '123456' 

ответ

3

Вы можете попробовать положить @Fetch(FetchMode.JOIN) на имущество Статья. Однако это аннотация Hibernate.

import org.hibernate.annotations.Fetch; 
import org.hibernate.annotations.FetchMode; 

//... 

@ManyToOne 
@Fetch(FetchMode.JOIN) 
Article article; 
+0

для меня это не решило проблему! –

+0

Я не знаю, как это должно решить проблему.AFAIK Fetchmode указывает только, как извлекать данные для инициализации объекта в памяти, а не как выполнять объединения в запросе. –

1

Насколько я мог выкопать, Hibernate не предлагают способ изменить неявную форму по умолчанию ассоциации присоединения к HQL Query.

В лучших решений я мог бы найти для себя были:

  • Постройте запрос с Явной информации;
  • Критерии использования, которые, вероятно, лучше всего подходят для построения динамических запросов.
+0

ОП не сказал, что есть что-то динамичное. Я что-то пропустил? –

+0

Использование «0212» и «123456» предполагает изменение запроса во время выполнения. Одно из решений, которое я нашел для «использования правильного соединения SQL», вместо этого использовал API критериев. И это кажется более естественным. –

+0

Критерии API обычно сложнее использовать и менее эффективны, чем HQL. Если меняются только значения, просто введите параметры в запрос. Это не очень «динамично», оно параметризовано. –

0

Прежде всего, если вы попытаетесь использовать o.article.nummer вместо a.nummer, я верю, что он добавит дополнительное предложение WHERE с внутренним соединением. Thre не может явно сказать левые соединения. Но вы сами указываете это в запросе, поэтому просто используйте объединенную сущность из псевдонима a.number = '23456'.

Поскольку вы знаете, что поле является нулевым, вы не можете использовать = так же, как вы не можете использовать = в SQL для полей с нулевым значением. Вместо того, чтобы использовать COALESCE для преобразования NULL значения в пустую строку для этой цели:

SELECT o FROM Offer o 
    LEFT OUTER JOIN o.article a 
    LEFT OUTER JOIN o.vendor v 
     WHERE v.number = '0212' 
     OR COALESCE(a.nummer,'') = '123456' 
0

Я был похожа проблема: у меня был какой-то GeneralFacility -Таблицы, который содержал столбец SpecificType. Не все объекты имели этот тип, и поскольку SpecificType был внутренним соединенным в записи GeneralFacility-Table без определенного типа, попадавшего под таблицу.

Я решил проблему, поставив

@Fetch(FetchMode.SELECT) 

рядом с @ManyToOne -LINE в модели. Тип теперь извлекается в отдельный запрос, и если это ничего не возвращает, результаты запроса GeneralFacility НЕ отбрасываются.

+0

Я предполагаю, что это применимо только при получении объекта, например. используя 'session.get'. Когда вам нужно свойство в запросе HQL, оно не имеет никакого влияния, насколько я знаю. –