Gerade so viele Parents auswählen, dass mindestens 20 Children angezeigt werden

N

nillehammer

Gast
Hallo Forum,
Ich habe folgendes JPA-Entitymodell
Java:
public class ProduktGruppe {
...
  @OneToMany(orphanRemoval = true, cascade = { PERSIST, MERGE }, mappedBy = "produktGruppe")
  @OrderBy("id")
  private Set<Produkt> produkte;
...
}

public class Produkt {
...
  @ManyToOne(optional = false, fetch = EAGER)
  @JoinColumn(name = "produktGruppe_id", nullable = false, insertable = true, updatable = false)
  private ProduktGruppe produktGruppe
...

Mit diesem Modell möchte ich nun gerade so viele Produktgruppen aus der Datenbank laden, so dass ich mindestens 20 Produkte anzeigen kann. Beispiel: Gruppe1 enthält 12 Produkte, Gruppe2 14. Ich hab meine mindestens 20 Produkte zusammen und kann die beiden Gruppen anzeigen.

Im Moment mache ich es so, dass ich mir alle Produktgruppen in eine Liste hole und dann im Java-Code solange über sie iteriere, bis ich meine mindestens 20 Produkte zusammen habe.

Ich bin schon den ganzen Tag am rumprobieren, um eine JPQL-Query hinzukriegen, die mir gleich eine Liste liefert, die nur so viele Produktgruppen enthält, dass ich die 20 Produkte zusammen habe. Ich bekomm's einfach nicht hin.
 

Noctarius

Top Contributor
Ob's da jetzt was allgemeines gibt weiß ich spontan gar nicht aber unter EclipseLink gibt es ScrollableCursor und unter Hibernate ScrollableResults. Bei OpenJpa gibt es da sicher auch was.

Möglicherweise gibt es im JPA 2.0 Standard auch eine fertige API dafür aber die habe ich noch nicht benutzt.
 
G

Gelöschtes Mitglied 5909

Gast
Java:
query.setFirstResult(0);
query.setMaxResults(20);
 
N

nillehammer

Gast
Ob's da jetzt was allgemeines gibt weiß ich spontan gar nicht aber unter EclipseLink gibt es ScrollableCursor und unter Hibernate ScrollableResults

Das stimmt, damit kann ich das Laden aller Entities vermeiden. Das ist aber nur eine Teillösung, weil ich im Zweifel trotzdem immer noch mehr ProduktGruppen lade, als ich müsste. Oder aber ich lade zu wenig und ich muss nachladen.

Tatsächlich mache ich es aber genau so jetzt auch. Ich lade eine einzelne ProduktGruppe speichere sie in einer Liste, lade die nächste usw. Bis ich die Marke von 20 Produkte überschritten habe. Das bedeutet zwar in der Regel je nach dem 2 bis 5 Selects statt einem einzigen, aber dafür gehe ich nicht über die komplette Tabelle und Hibernate muss mir nur die Objekte erzeugen, die ich tatsächlich verwende.
 
Zuletzt bearbeitet von einem Moderator:
N

nillehammer

Gast
query.setFirstResult(0);
query.setMaxResults(20);
Das bringt ja überhaupt nichts. Damit lade ich dann 20 Produktgruppen, ohne die Summe aller Produkte zu berücksichtigen, die sie enthalten.

Oder ich lade damit 20 Produkte. Das will ich aber nicht, weil dann mit ziemlicher Sicherheit die ProduktGruppe, zu der die letzten Produkte dieser Abfrage gehören, nicht vollständig angezeigt wird.
 
G

Gelöschtes Mitglied 5909

Gast
Und wieso lädst du dir nicht 20 Produkte und dann die passende gruppe dazu?

// edit:

mit einem select wird das wohl eh nicht gehn.

lade zwanzig produkte, sortier sie nach product.produktGruppe.id und lade danach noch die letzte pruductgruppe und stopf alles in ein set.
 
Zuletzt bearbeitet von einem Moderator:
N

nillehammer

Gast
Und wieso lädst du dir nicht 20 Produkte und dann die passende gruppe dazu?
Wenn ich so drüber nachdenke...
Weil ich, um die Gruppen herauszufinden, über die Liste der zwanzig Produkte iterieren müsste. Aber, wenn ichs mir recht überlege, ist das trotzdem noch effizienter als nach und nach jede ProduktGruppe einzeln nach zuladen.
 
N

nillehammer

Gast
Die Lösung mit dem Laden der Produkte hatte den Nachteil, dass leere Produktgruppen nie angezeigt werden. Deswegen hab ich weiter nachgedacht und hab jetzt eine einigermaßen elegante Lösung, die mit einem einzigen Select für das Laden der ProduktGruppen auskommt. Der JPQL-String sieht so aus
"SELECT pg FROM ProductGrupe pg LEFT JOIN pg.produkte ORDER BY pg.id WHERE pg.id > :id"

Mit diesem Select kreiere ich eine TypedQuery<ProduktGruppe>, mach dann setMaxResults(...) und hole mir die resultList. Ich bekomme eine Liste mit 20 Einträgen, worin durch das LEFT JOIN mit Produkt auch die leeren ProduktGruppen enthalten sind. Viele Einträge sind in der Liste doppelt. Das ist auch gewollt. Ich will ja nicht 20 verschiedene ProduktGruppen laden, sondern soviele unterschiedliche, dass ich auf mindestens 20 Produkte komme. Die Liste adde ich mit addAll() in ein SortedSet, dass ich mit einem IdComparator intitalisiert habe. Am Ende habe ich ein SortedSet, in dem genau die Gruppen drinnen sind, die ich anzeigen will.

Ein kleiner Nachteil besteht noch. Theoretisch könnte ich mit der Query 20 leere Produktgruppen laden und überhaupt keine Produkte anzeigen. Das ist aber bei meinem Datenbestand (noch) ausgeschlossen. Außerdem wäre es auch ok. Weil 20 leere Produktgruppen etwa soviel Platz für die Anzeige brauchen, wie z.B. 3 mit Produkten und ich die leeren Produktgruppen ja auch anzeigen will.
 
Ähnliche Java Themen

Ähnliche Java Themen


Oben