2016-06-20 13 views
6

ich JPA-Entität wie diese mit der Liste haben:Stream auf JPA faul Liste

@OneToMany(mappedBy = "scadaElement", orphanRemoval = true) 
private List<ElementParameter> elementParameters; 

und Kartenform Elemente

@ManyToOne 
@JoinColumn(name = "SCADAELEMENT_ID") 
ScadaElement scadaElement; 

wenn ich Einheit mit Elementeliste und Strom tun auf sie nichts tun Stroms, , selbst wenn ich eine Liste mit .size() trigge, aber wenn ich dasselbe mit einer for-Schleife mache, funktioniert es.

System.out.println("elements size: " + s.getElementParameters().size()); 
s.getElementParameters() 
      .stream() 
      .forEach(
        a -> { 
         System.out.println("elementId: " + a.getId()); 
        } 
      ); 

Gibt es eine Lösung, um diesen Stream zu arbeiten? Ich benutze eclipselink als JPA-Provider.

+0

Versuchen Sie, die neuesten Versionen von Eclipselink unterstützen, wie bei Ihnen keine Unterstützung in den faulen Sammlungen gebaut gehabt haben könnten. – Chris

Antwort

5

Anscheinend beziehen Sie sich auf this issue. Diese faulen Listen, die das Anti-Pattern verwenden, das von tatsächlichen Implementierungen erbt (hier Vector), passen sich nicht an die Entwicklung der Basisklasse an. Beachten Sie, dass es zwei mögliche Ergebnisse, je nachdem, wie die anti-Muster

  • Wenn die träge bevölkerten Liste füllt sich (es hinsichtlich des ererbten Zustand) auf der ersten Nutzung realisiert wurde, beginnen die neuen geerbten Methoden arbeiten als Sobald eine Triggereigenschaft zum ersten Mal aufgerufen wurde
  • Wenn die Liste jedoch alle Zugriffsmethoden überschreibt, um die Delegierung an eine andere Implementierung zu erzwingen, ohne den Status der Basisklasse zu aktualisieren, die Methoden der Basisklasse, die nicht überschrieben wurden funktioniert nie, selbst wenn die Liste ausgefüllt wurde (aus der Sicht der Unterklasse)

Offensichtlich gilt der zweite Fall für Sie. Wenn die Population der Liste ausgelöst wird, funktioniert die vererbte Methode forEach nicht. Beachten Sie, dass das Ausschalten der faulen Bevölkerung über die Konfiguration hier die einfachere Lösung sein könnte.


Für mich ist die sauberste Lösung wäre, wenn IndirectList erbt von AbstractList und zur Kollektions API-Standard entspricht, jetzt, fast 20 Jahre nach der Sammlung API abgelöst hat Vector (sollte ich erwähnen, wie viel jünger JPA tatsächlich ist ?). Leider sind die Entwickler diesen Weg nicht gegangen. Stattdessen wurde das Anti-Pattern ausgereizt, indem eine andere Klasse erstellt wurde, die von der Klasse erbt, die bereits von der Klasse erbt, die nicht für die Vererbung vorgesehen ist. Diese Klasse überschreibt die in Java 8 eingeführten Methoden und erhält möglicherweise eine weitere Unterklasse in einer der nächsten Java-Versionen.

Die gute Nachricht ist, Entwickler jeden List erwarten sein, um ein Vector müssen nicht ihre Meinung bilden, aber die schlechte Nachricht ist, it doesn’t work wie manchmal, Sie werden nicht die erweiterte Java 8 spezifische Version mit JPA 2.6 erhalten. Aber offensichtlich wird JPA 2.7 funktionieren.

So können Sie ein paar alternative Lösungen ableiten:

  • faul Bevölkerung
  • Bleiben Sie mit Java 7
  • Warten Sie, JPA 2.7
  • nur die Sammlung kopieren, deaktivieren z.B.
    List<ElementParameter> workList=new ArrayList<>(elementParameters);
    Diese workList alle Sammlung & Stream-Operationen
+0

Danke, ich werde 4. Metod, Coping Liste auf neue Liste am besten aussehen. – simo