Dies ist tatsächlich das erwartete Verhalten, wenn ich Ihre Konfiguration richtig verstanden habe.
Der Ruhezustand gibt keine eindeutigen Ergebnisse für eine Abfrage mit aktiviertem Outer Join-Abruf für eine Sammlung zurück (selbst wenn ich das eindeutige Schlüsselwort verwende). Zunächst müssen Sie SQL verstehen und wissen, wie OUTER JOINs in SQL funktionieren. Wenn Sie äußere Verknüpfungen in SQL nicht vollständig verstehen und verstehen, lesen Sie dieses FAQ-Element nicht weiter, sondern konsultieren Sie ein SQL-Handbuch oder ein Lernprogramm. Andernfalls verstehen Sie die folgende Erklärung nicht und beschweren sich im Hibernate-Forum über dieses Verhalten.
Typische Beispiele, die möglicherweise doppelte Referenzen desselben Order-Objekts zurückgeben:
List result = session.createCriteria(Order.class)
.setFetchMode("lineItems", FetchMode.JOIN)
.list();
<class name="Order">
...
<set name="lineItems" fetch="join">
List result = session.createCriteria(Order.class)
.list();
List result = session.createQuery("select o from Order o left join fetch o.lineItems").list();
Alle diese Beispiele erzeugen dieselbe SQL-Anweisung:
SELECT o.*, l.* from ORDER o LEFT OUTER JOIN LINE_ITEMS l ON o.ID = l.ORDER_ID
Möchten Sie wissen, warum die Duplikate vorhanden sind? Schauen Sie sich die SQL-Ergebnismenge an. Hibernate versteckt diese Duplikate nicht auf der linken Seite des äußeren verbundenen Ergebnisses, sondern gibt alle Duplikate der Treibertabelle zurück. Wenn Sie 5 Bestellungen in der Datenbank haben und jede Bestellung 3 Werbebuchungen enthält, besteht die Ergebnismenge aus 15 Zeilen. Die Java-Ergebnisliste dieser Abfragen enthält 15 Elemente vom Typ Order. Von Hibernate werden nur Instanzen mit 5 Ordnungen erstellt, Duplikate der SQL-Ergebnismenge bleiben jedoch als doppelte Verweise auf diese 5 Instanzen erhalten. Wenn Sie diesen letzten Satz nicht verstehen, müssen Sie sich über Java und den Unterschied zwischen einer Instanz auf dem Java-Heap und einem Verweis auf eine solche Instanz informieren.
(Warum eine linke äußere Verknüpfung? Wenn Sie eine zusätzliche Bestellung ohne Werbebuchungen haben würden, würde die Ergebnismenge 16 Zeilen umfassen, wobei NULL die rechte Seite ausfüllt, wobei die Positionsdaten für eine andere Bestellung gelten. Sie möchten Bestellungen, auch wenn Sie haben keine Werbebuchungen, oder? Wenn nicht, verwenden Sie einen inneren Join-Abruf in Ihrem HQL.
Der Ruhezustand filtert diese doppelten Referenzen standardmäßig nicht heraus. Einige Leute (nicht Sie) wollen das tatsächlich. Wie können Sie sie herausfiltern?
So was:
Collection result = new LinkedHashSet( session.create*(...).list() );