2016-05-11 10 views
0

Ich habe zwei Entitäten lassen sagen A und B, abgebildet, wie unten:Ist es gültig Verhalten von Hibernate (JPQL Query OneToMany)

public class A{ 
    ... 
    @OneToMany(mappedBy = "a", cascade = CascadeType.ALL) 
    Set<B> bs 
} 

public class B{ 
    ... 
    String someProp; 
    ... 
    @ManyToOne 
    @JoinColumn(name = "A_ID") 
    A a 
} 

Einige Entitätsinstanz von A hat zwei Elemente von B in einer Datenbank.

Wenn ich ausführen einfache Abfrage für A wie:

entityManager.createQuery("SELECT a FROM A a WHERE a.id = 1").getSingleResult(); 

und alles wie erwartet funktioniert, habe ich eine Instanz mit zwei Instanzen von B im Set, aber wenn ich ausgeführt Abfrage:

Query query = entityManager.createQuery("SELECT a FROM A a JOIN FETCH a.bs b WHERE b.someProp= :somePropParam"); 
query.setParameter("somePropParam","somePropValue"); 
query.getResultList(); 

Ich habe Instanz von A mit einem Element von B in der Menge (Element, nach dem ich frage).

I modifizierte Abfrage:

entityManager.createQuery("SELECT b.a FROM B b JOIN b.a a WHERE b.someProp = :somePropParam.. more a conditions); 
//.... this query works. 

Sollten alle Instanzen von B nicht erste Abfragelast? Sollte Hibernate keine zusätzliche Abfrage ausführen, um alle zu laden?

+0

in A. zu bauen, wenn die A, der zurückgegeben wird (durch eine Abfrage, die A als Rückgabetyp hat) hat wirklich zwei Elemente in seiner Sammlung dann, wenn Sie das Sammelgebiet der Zugang zurückgegebenes Objekt sollten Sie _always_ immer 2 Elemente finden. –

+0

Ich denke, es sollte 2 Element in "bs" Satz von A zurückgeben, aber es gibt nur einen zurück, da es von '/ ** Spalten von a und b **/ von A eine innere Verbindung A b auf a zurückgegeben wurde .id = b.a_id wo b.someProp = 'someProperty'' Es gibt keine zusätzliche Abfrage, um zusätzliche B-Tabellenzeilen zu laden, die NICHT die Bedingung 'b.someProp =' someProperty'' erfüllen –

+0

Es könnte" erwartetes Verhalten "sein in Hibernate aber sicherlich nicht in anderen Implementierungen ... –

Antwort

1

Es ist erwartetes Verhalten. Dies ist eine häufige Falle. Die Methode getSingleResult gibt die erste Zeile zurück. Wenn es mehr als einen B gibt, enthält der Ergebnissatz natürlich mehr als einen Eintrag, aber Sie erhalten nur den ersten Eintrag. Das mag ein bisschen seltsam erscheinen.

Aber sehen Sie es als eine einfache Abfrage mit setMaxResult (1) und einem klassischen SQL-Join. Es würde mit dem gleichen Ergebnis enden. Das ist auch der Grund, warum Hibernate Subselects für untergeordnete Beziehungen verwendet, wenn Sie das Eager-Holen verwenden.

Wenn Sie eine große Anzahl an untergeordneten Daten erwarten, fordern Sie die childs mit einer zusätzlichen Abfrage an und vermeiden Sie bidirektionale 1: n-Zuordnungen. Eine Beziehung vom Elternteil zum Kind sollte einen guten Grund haben, da es auf lange Sicht oft zu Problemen führen kann.

Zusätzliches Beispiel betrachten das folgende. Sie verwenden Ihre Abfrage und setMaxResult (10). Die mögliche Ergebnismenge, die garantiert, dass Sie 10 Einträge des Elternteils erhalten, ist unbegrenzt. Der Hibernate hätte also keine Chance, die korrekte Datenmenge anzufordern. Dies kann dazu führen, dass eine große Menge an Daten abgerufen wird, ohne sie zu benötigen.

1

SQL erstellt für:

Query query = entityManager.createQuery("SELECT a FROM A a JOIN  FETCH a.bs b WHERE b.someProp= :somePropParam"); 
    query.setParameter("somePropParam","somePropValue"); 
    query.getResultList(); 

wie folgt lautet:

select /** columns from a and b **/ 
from A a inner join A b on a.id=b.a_id 
where b.someProp='someProperty' 

Es ist richtig SQL Ergebnis nach Bedingung (1 Zeile zurückgegeben) es sagt mir, „Ja, es gibt eine Instanz von A fulfiling die Bedingung, die Sie bekommen, hier sind Sie ", aber ich dachte, dass mit" JOIN FETCH a.bs "ich Hiberante zwingen, alle" bs "Sammlung eifrig zu laden, auch wenn Elemente von der ersten Abfrage nicht zurückgegeben werden. Ich dachte, Hibernate führen zusätzliche Abfrage wie

SELECT b. * FROM B b WHERE b.a_id = (ID von der Abfrage oben zurückgegeben).

komplette Sammlung von Bs

+0

Es sollte. Es tut es nicht –