Подтвердить что ты не робот

Hibernate/JPA: как заставить неявные объединения использовать LEFT OUTER JOINS

Существует класс Offer, который имеет необязательное отношение к классу Article. Так что некоторые свойства статьи содержат значение null.

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

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'
4b9b3361

Ответ 1

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

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

//...

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

Ответ 2

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

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

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

Ответ 3

Прежде всего, если вы попытаетесь использовать 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'

Ответ 4

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

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

    @Fetch(FetchMode.SELECT)

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