Questo è in realtà il comportamento previsto se ho capito correttamente la tua configurazione.
Hibernate non restituisce risultati distinti per una query con il recupero del join esterno abilitato per una raccolta (anche se utilizzo la parola chiave distinta)? Innanzitutto, è necessario comprendere SQL e come funzionano gli OUTER JOIN in SQL. Se non comprendi e comprendi appieno gli outer join in SQL, non continuare a leggere questo articolo delle domande frequenti ma consulta un manuale o un'esercitazione SQL. Altrimenti non capirai la seguente spiegazione e ti lamenterai di questo comportamento sul forum di Hibernate.
Esempi tipici che potrebbero restituire riferimenti duplicati dello stesso oggetto Order:
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();
Tutti questi esempi producono la stessa istruzione SQL:
SELECT o.*, l.* from ORDER o LEFT OUTER JOIN LINE_ITEMS l ON o.ID = l.ORDER_ID
Vuoi sapere perché ci sono i duplicati? Guarda il set di risultati SQL, Hibernate non nasconde questi duplicati sul lato sinistro del risultato del join esterno ma restituisce tutti i duplicati della tabella guida. Se hai 5 ordini nel database e ogni ordine ha 3 voci, il gruppo di risultati sarà di 15 righe. L'elenco dei risultati Java di queste query avrà 15 elementi, tutti di tipo Order. Solo 5 istanze di Order verranno create da Hibernate, ma i duplicati del set di risultati SQL vengono conservati come riferimenti duplicati a queste 5 istanze. Se non capisci quest'ultima frase, devi leggere su Java e la differenza tra un'istanza sull'heap Java e un riferimento a tale istanza.
(Perché un join esterno sinistro? Se avessi un ordine aggiuntivo senza elementi pubblicitari, il set di risultati sarebbe 16 righe con NULL che riempie il lato destro, dove i dati dell'elemento pubblicitario sono per l'altro ordine. Vuoi ordini anche se non hanno elementi pubblicitari, giusto? In caso contrario, utilizza un inner join fetch nel tuo HQL).
Hibernate non filtra questi riferimenti duplicati per impostazione predefinita. Alcune persone (non tu) lo vogliono davvero. Come puoi filtrarli?
Come questo:
Collection result = new LinkedHashSet( session.create*(...).list() );