Criteria API: Abrufen einer Liste zurückgibt wiederholt Hauptsache
Habe ich die folgenden Entitäten; Ticket enthält einen Satz von 0,N WorkOrder:
@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;
}
Ich bin be-Tickets und abrufen der Attribute. Alle 0,1 Attribute stellen kein problem dar. Für Arbeitsaufträge, die ich verwendet, diese Antwort zu erhalten, den folgenden code.
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();
Das Ergebnis ist, dass in einer Abfrage zurückgeben soll mir 1 Ticket mit 5 Arbeitsaufträge, ich bin das abrufen der gleichen Ticket 5 mal.
Wenn ich nur die Arbeitsaufträge ein eifriger Abrufen und löschen Sie die fetch-code, es funktioniert wie es sollte.
Kann mir jemand helfen? Vielen Dank im Voraus.
UPDATE:
Einer Erklärung, warum ich nicht einfach glücklich mit JB Nizet Antwort (auch wenn es am Ende funktioniert).
Wenn ich nur die Beziehung eifrig, JPA prüft genau die gleichen Daten, wenn ich es faul, und fügen Sie die fetch-Klausel, um die Kriterien /JPQL. Die Beziehungen zwischen den verschiedenen Elementen ist auch klar, wie definiere ich das ListAttribute
für die Kriterien der Abfrage.
Gibt es einige vernünftige explanaition aus dem Grund, dass der PPV nicht wieder die gleichen Daten in beiden Fällen?
UPDATE FÜR BOUNTY: Während JB Nizet Antwort hat und das Problem lösen, ich finde es trotzdem sinnlos, dass, da zwei Operationen mit der gleichen Bedeutung ("Bekommen Ticket
und holt alle WorkOrder
innen ticket.workOrders
"), das tun Sie, indem Sie ein eager loading braucht keine weiteren änderungen, während die Angabe einer fetch-Anweisung erfordert ein DISTINCT
Befehl
- Wenn Sie einen Blick auf Linke Verknüpfung, es ist die Art, wie es funktioniert. Warum brauchen Sie, um Ergebnisse zu Holen, die von leftjoin?
- Von den drei verfügbaren Optionen in der Kriterien-API, es ist sinnvoller. Wir sprechen über den PPV hier, so dass ich erwartet, dass die API zu organisieren, die SQL-Entitäten in einem mehr richtige Weg.
- Siehe meine bearbeitete Antwort.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Gibt es einen Unterschied zwischen eager loading und fetch-join. Eager loading, bedeutet nicht, dass die Daten geladen sind innerhalb der gleichen Abfrage. Es bedeutet nur, dass es sofort geladen werden, obwohl durch zusätzliche Abfragen.
Den Kriterien ist immer übersetzt, um eine SQL-Abfrage. Wenn Sie angeben, Verknüpfungen, es wird join in SQL. Durch die Art der SQL multipliziert, die Daten der root-Einheit sowie, das führt zu dem Effekt, den Sie bekam. (Beachten Sie, dass Sie das gleiche Instanz mehrere Male, so dass das root-Element wird nicht multipliziert in Erinnerung.)
Gibt es mehrere Lösungen für das:
distinct(true)
.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)
).DetachedCriteria
).Haben Sie versucht, Sie anzurufen
distinct(true)
auf die CriteriaQuery?JPA-2-Spezifikation, Seite 161, der sagt:
Die javadoc sagt auch:
Den Grund, warum Sie brauchen nicht die deutliche, wenn der Verein ist mit Spannung geladen ist wahrscheinlich nur, dass der Verein nicht geladen ist, mit einem fetch-join, aber mit einer zusätzlichen Abfrage.
distinct(true)
es funktioniert. Aber ist es die "richtige" Lösung oder nur ein workaround? Ich finde widersprüchlich, dass ich sage PPV, ich bin gerade auf der Suche nachTicket
und dass die Arbeitsaufträge müssen geladen werden, in einer Liste, und das JPA gibt mir einfach das kartesische Produkt.