2016-03-23 10 views
0

Ich habe eine Klasse, dieRuhe HQL eifrig Last Sammlung in eingebettetes Objekt

public class A { 
    @Embedded 
    private B b; 

    // getter setter 
} 

Innen B Klassenobjekt eingebettet ist, habe ich eine Sammlung z.B.

@Embeddable 
public class B { 
    @OneToMany(fetch=FetchType.LAZY) 
    @JoinColumn(name="A_ID") 
    List<C> cList; 
} 

und Klasse C

@Entity 
public class C { 
    // not important 
} 

Jetzt möchten ich ein Objekt mit HQL abzufragen und auch die C-Liste mit Spannung abrufen. Ich habe versucht,

select a from A a join fetch a.b.c c 

aber ich bekomme diese Fehlermeldung Join fetch: “query specified join fetching, but the owner of the fetched association was not present in the select list”

Ich lese diese Join fetch: "query specified join fetching, but the owner of the fetched association was not present in the select list" und es scheint, dass es ist, weil meine Sammlung im Inneren ein eingebettetes Objekt gespeichert wird.

Natürlich kann ich for Schleife tun und Hibernate.initialize verwenden, aber die Leistung wird fallen, wenn mehr Daten abgerufen werden.

Ist es möglich, dies in HQL auf einen Schlag zu tun?

Antwort

1

Es ist möglich, die eingebettete Sammlung mit HQL zu laden. Ich glaube, du musst deine HQL etwas modifizieren.

Ich habe mit folgenden Einrichtungen getestet:

HINWEIS: Added Multi auf Ihre Entitätsnamen wie ich bereits Klassen mit demselben Namen A, B und C in meinem Arbeitsbereich und hinzugefügt @Id Annotation zusammen mit toString Verfahren usw.

@Entity 
class MultiA { 
    public MultiA() {} 

    public MultiA(List<MultiC> cList) { 
     this.b.cList = cList; 
    } 

    @Id 
    @GeneratedValue(strategy=GenerationType.IDENTITY) 
    public int id; 
    @Embedded 

    public MultiB b = new MultiB(); 
    @Override 
    public String toString() { 
     return "MultiA [id=" + id + ", b=" + b + "]"; 
    } 

} 

@Embeddable 
class MultiB { 
    @OneToMany(fetch=FetchType.LAZY, cascade=CascadeType.ALL) 
    @JoinColumn(name="A_ID") 
    List<MultiC> cList = new ArrayList<MultiC>(); 

    @Override 
    public String toString() { 
     return "MultiB [cList=" + cList + "]"; 
    } 

} 

@Entity 
class MultiC { 
    @Id 
    @GeneratedValue(strategy=GenerationType.IDENTITY) 
    public int id; 

    @Override 
    public String toString() { 
     return "MultiC [id=" + id + "]"; 
    } 
} 

Und schließlich die HQL verwendet wird:

session1.createQuery("select distinct a from MultiA a join fetch a.b.cList").list() 

Dies führt zu der unter einzelnen SQL Brennen verbinden mit:

Hibernate: select distinct multia0_.id as id1_0_0_, clist1_.id as id1_1_1_, clist1_.A_ID as A_ID2_1_0__, clist1_.id as id1_1_0__ from MultiA multia0_ inner join MultiC clist1_ on multia0_.id=clist1_.A_ID 

und gibt die folgende Ausgabe, die bevölkert zusammen mit MutliC 2 Einheiten von MultiA zurückgibt.

[MultiA [id=1, b=MultiB [cList=[MultiC [id=1], MultiC [id=2], MultiC [id=3]]]], 
MultiA [id=2, b=MultiB [cList=[MultiC [id=6], MultiC [id=4], MultiC [id=5]]]]] 
+0

Dies ist genau das, was ich suche! Zusammenfassend muss ich den Alias ​​für den Join-Abruf nicht angeben. –

+0

Darüber hinaus denke ich, dass "linker äußerer Join" hier nützlich ist, da die Verwendung von "äußerer Join" nur MultiA-Objekte mit MultiC-Sammlung abruft –

1

Versuchen Sie den Alias ​​für c in der HQL entfernen, wie folgt aus:

select a from A a join fetch a.b.c 

Der Alias ​​nur erforderlich, wenn Sie es direkt in einem where oder select Klausel verwenden müssen, und auch, wenn Sie tun müssen, einige Joins von Attributen der c Klasse.