2016-06-20 47 views
6

ho JPA entità con la lista in questo modo:torrente su APP lista pigro

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

e la forma mappa ElementParameter

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

quando ottengo entità con la lista elementParameters e faccio flusso su di esso STREAM non fare nulla , anche quando trigger elenco con .size() ma quando faccio lo stesso con un ciclo for funziona.

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

C'è qualche soluzione per far funzionare quel flusso? Io uso eclipselink come provider JPA.

+0

provare le ultime versioni EclipseLink, come il vostro potrebbe non hanno avuto il supporto integrato nelle collezioni pigri. – Chris

risposta

5

Apparentemente, si sta facendo riferimento a this issue. Queste liste pigre che utilizzano l'anti-pattern di ereditare dalle implementazioni reali (qui Vector) non si adattano all'evoluzione della classe base. Si noti che ci sono due possibili risultati a seconda di come l'anti-modello è stato realizzato

  • Se l'elenco pigramente popolato stesso (termini IT dello stato ereditato) sul primo utilizzo popola, i nuovi metodi ereditati inizieranno a lavorare come appena una proprietà trigger è stata aperta per la prima volta
  • Ma se l'elenco sovrascrive tutti i metodi accessor per applicare la delega a un'altra implementazione, senza mai aggiornare lo stato della classe base, i metodi della classe base 'che non sono stati sovrascritti non inizierà mai a funzionare, anche se l'elenco è stato compilato (dal punto di vista della sottoclasse)

Apparentemente, il secondo caso si applica a voi. Attivare la popolazione dell'elenco non rende il metodo ereditato forEach. Si noti che disattivare la popolazione pigra tramite la configurazione potrebbe essere la soluzione più semplice qui.


Per me, la soluzione più pulita sarebbe se IndirectList eredita da AbstractList e aderisce allo standard Collection API, ora, quasi vent'anni dopo l'API Collection ha superato Vector (dovrei parlare di quanto molto più giovane JPA in realtà è ?). Sfortunatamente, gli sviluppatori non hanno intrapreso questa strada. Invece, l'anti-pattern è stato massimizzato creando un'altra classe che eredita dalla classe che già eredita dalla classe non progettata per l'ereditarietà. Questa classe sovrascrive i metodi introdotti in Java 8 e forse ottiene un'altra sottoclasse in una delle prossime versioni di Java.

Quindi la buona notizia è che gli sviluppatori aspettavano ogni List essere un Vector non c'è bisogno di fare le loro menti, ma la cattiva notizia è it doesn’t work come a volte, non sarà possibile ottenere la versione estesa specifica Java 8 con JPA 2.6. Ma a quanto pare, JPA 2.7 funzionerà.

Così si può derivare un paio di soluzioni alternative:

  • spegnere popolazione pigro
  • Resta con Java 7
  • Attendere JPA 2.7
  • basta copiare la raccolta, ad esempio,
    List<ElementParameter> workList=new ArrayList<>(elementParameters);
    Questo workList sosterrà tutte Collection & operazioni Ruscello
+0

Grazie, userò il 4 ° metodo, la lista di coping alla nuova lista ha un aspetto migliore. – simo