2012-01-25 14 views
13

Istnieje klasa Offer że ma opcjonalnego relacji do klasy Article. Aby niektóre oferty artykułów posiadały wartość null.Hibernate/JPA: Jak zmusić niejawna dołącza do korzystania LEFT sprzężenia zewnętrzne

Jeśli użyję następującego oświadczenia, wszystko działa poprawnie. Mam wszystkie oferty, nawet te, które nie mają żadnego artykułu.

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' 

jeśli zmienić oświadczenie:

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' 

dostałem tylko te oferty o artykuły różne od NULL. Dzieje się tak, ponieważ notacja dla niejawnych połączeń (o.article.nummer) wymusza wewnętrzne sprzężenie.

Czy istnieje możliwość narzucenia lewych złączeń zewnętrznych na niejawne łączenia (adnotacja sterowana lub coś innego)? Jeśli jest szansa, że ​​przydałby się krótki formularz tak:

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

Odpowiedz

3

Można spróbować umieścić @Fetch(FetchMode.JOIN) na posesji art. Jest to jednak adnotacja typu Hibernate.

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

//... 

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

dla mnie to nie rozwiązało problemu! –

+0

Nie wiem, jak to rozwiązać problem.AFAIK Fetchmode określa tylko, jak pobrać dane, aby zainicjować obiekt w pamięci, a nie jak robić sprzężenia w zapytaniu. –

1

ile mogłem kopać, Hibernate nie ofertę sposób zmienić domyślny ukrytą formę stowarzyszenia łączącego dla zapytania HQL.

W najlepsze rozwiązania mogę znaleźć dla siebie byli:

  • zbudować kwerendę z wyraźną dołączenia informacji;
  • Kryteria użycia, które najlepiej nadaje się do dynamicznego budowania zapytań.
+0

PO nie powiedział, że jest coś dynamicznego. Przegapiłem coś? –

+0

Używanie "0212" i "123456" sugeruje zmiany zapytania w czasie wykonywania. Jednym z rozwiązań, które znalazłem dla "użycia odpowiedniego sprzężenia SQL", było użycie API Criteria. I wydaje się bardziej naturalne. –

+0

Kryteria API są zwykle bardziej skomplikowane w użyciu i mniej wydajne niż HQL. Jeśli zmieniają się tylko wartości, po prostu umieść parametry w zapytaniu. To nie jest tak naprawdę "dynamiczne", jest parametryzowane. –

0

Po pierwsze, jeśli spróbujesz użyć o.article.nummer zamiast a.nummer, uważam, że doda on dodatkową klauzulę WHERE z wewnętrznym sprzężeniem. Nie można jednoznacznie powiedzieć lewych złączeń. Ale tak czy inaczej określasz to w zapytaniu, więc po prostu użyj połączonego elementu z aliasu a.number = '23456'.

Ponieważ wiesz, że pole jest zerowe, nie możesz użyć = tak, jak nie możesz użyć = w SQL na polach z zerami. Zamiast używać COALESCE do konwersji wartości NULL do pustej struny do tego celu:

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

miałem similiar problem: Miałem jakieś GeneralFacility -Tabela który zawierał Kolumna SpecificType. Nie wszystkie obiekty miały ten typ, a ponieważ obiekt typu SpecificType był połączony wewnętrznie, wpisy w tabeli GeneralFacility nie zawierały określonego typu.

I rozwiązać problem poprzez umieszczenie

@Fetch(FetchMode.SELECT) 

obok @ManyToOne -line w modelu. Typ jest teraz pobierany w oddzielnej kwerendzie i jeśli to nie zwróci nic, wyniki kwerendy GeneralFacility NIE są odrzucane.

+0

Chyba ma to zastosowanie tylko wtedy, gdy pobierasz encję np. przy użyciu 'session.get'. Kiedy potrzebna jest właściwość w kwerendzie HQL, nie ma ona wpływu na ile mi wiadomo. –

Powiązane problemy