Ho le seguenti Entità; Ticket contiene un insieme di 0, N WorkOrder:: Recupero di una lista restituisce entità principale ripetuta
@Entity
public class Ticket {
...
@OneToMany(mappedBy="ticket", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private List<WorkOrder> workOrders = null;
...
}
@Entity
public class WorkOrder {
...
@ManyToOne
@JoinColumn(nullable = false)
private Ticket ticket;
}
sto caricando I biglietti e andare a prendere gli attributi. Tutti gli attributi 0,1 non presentano alcun problema. Per gli ordini di lavoro, ho usato this answer per ottenere il seguente codice.
CriteriaBuilder criteriaBuilder = this.entityManager.getCriteriaBuilder();
CriteriaQuery<Ticket> criteriaQuery = criteriaBuilder
.createQuery(Ticket.class);
Root<Ticket> rootTicket = criteriaQuery.from(Ticket.class);
ListAttribute<? super Ticket, WorkOrder> workOrders =
rootTicket.getModel().getList("workOrders", WorkOrder.class);
rootTicket.fetch(workOrders, JoinType.LEFT);
// WHERE logic
...
criteriaQuery.select(rootTicket);
TypedQuery<Ticket> query = this.entityManager.createQuery(criteriaQuery);
return query.getResultList();
Il risultato è che, in una query che mi dovrebbe restituire 1 biglietto con 5 workorders, sto Recupero lo stesso biglietto per 5 volte.
Se faccio appena il lavoroOrders a Eager Fetch ed elimini il codice di recupero, funziona come dovrebbe.
Qualcuno può aiutarmi? Grazie in anticipo.
UPDATE:
Una spiegazione sul motivo per cui io non sono solo felice con la risposta di JB Nizet (anche se alla fine funziona).
Quando faccio la relazione desiderosa, JPA sta esaminando esattamente gli stessi dati che quando lo faccio pigro e aggiungo la clausola fetch ai criteri/JPQL. Anche le relazioni tra i vari elementi sono chiare, poiché definisco lo ListAttribute
per la query Criteri.
C'è qualche ragionevole spiegazione per il fatto che l'APP non restituisce gli stessi dati in entrambi i casi?
UPDATE per Bounty: Mentre la risposta di JB Nizet ha risolto il problema, trovo ancora privo di significato che, date due operazioni con lo stesso significato ("Get Ticket
a prendere tutte WorkOrder
all'interno ticket.workOrders
"), facendo loro da un eager loading non richiede ulteriori modifiche mentre specificare un recupero richiede un comando DISTINCT
Se si guarda a [Registrazione Sinistra] (http://www.w3schools.com/sql/sql_join_left.asp), è il modo in cui funziona. Perché hai bisogno di recuperare i risultati di leftjoin? – JMelnik
Delle tre opzioni disponibili nell'API dei criteri, è il più ragionevole. Stiamo parlando di JPA qui, quindi mi aspettavo che l'API organizzasse l'SQL nelle entità in modo più corretto. – SJuan76
Vedere la mia risposta modificata. –