2016-06-20 39 views
6

Mam podmiot WZP z listy tak:strumienia na JPA leniwe liście

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

i forma mapa ElementParameter

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

kiedy się podmiot z listy elementParameters i zrobić strumień na to strumień zrobić nic , nawet gdy wyzwalam listę przy pomocy .size(), ale gdy robię to samo z pętlą for, to działa.

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

Czy istnieje rozwiązanie, aby ten strumień działał? Używam eclipselink jako dostawcy JPA.

+0

wypróbować najnowsze wersje EclipseLink, jak twoje nie mogły mieć wsparcie wbudowany leniwych kolekcjach. – Chris

Odpowiedz

5

Najwyraźniej masz na myśli this issue. Te leniwe listy używające wzorca dziedziczenia z rzeczywistych implementacji (tutaj Vector) nie dostosowują się do ewolucji klasy bazowej. Należy pamiętać, że istnieją dwa możliwe wyniki w zależności od sposobu anty-wzorzec został zrealizowany

  • Jeśli leniwie zaludnionych lista zapełnia się (warunki IT dziedziczonej stanu) na pierwszym użyciu, nowe dziedziczone metody zacznie działać jako wkrótce po uzyskaniu dostępu do właściwości wyzwalacza po raz pierwszy
  • Ale jeśli lista unieważni wszystkie metody dostępu w celu wymuszenia delegowania do innej implementacji, bez aktualizowania stanu klasy bazowej, metody klasy podstawowej, które nie zostały nadpisane nigdy nie zacznie działać, nawet jeśli lista została zapełniona (z podklasy "punktu widzenia")

Najwyraźniej drugi przypadek dotyczy ciebie. Wywołanie populacji listy nie powoduje działania odziedziczonej metody forEach. Zauważ, że wyłączenie leniwej populacji poprzez konfigurację może być tutaj prostszym rozwiązaniem.


Dla mnie najczystszym rozwiązaniem byłoby, gdyby IndirectList dziedziczy z AbstractList i przylega do standardu Collection API, teraz, prawie dwadzieścia lat po API Collection zastąpiła Vector (należy wspomnieć, ile młodszy JPA rzeczywiście jest ?). Niestety deweloperzy nie poszli tą drogą. Zamiast tego antykreślenie zostało ograniczone przez utworzenie innej klasy, która dziedziczy po klasie, która już dziedziczy po klasie nieprzeznaczonej do dziedziczenia. Ta klasa ma pierwszeństwo przed metodami wprowadzonymi w Javie 8 i prawdopodobnie dostaje inną podklasę w jednej z następnych wersji Javy.

więc dobrą wiadomością jest to, programiści spodziewa każdy List być Vector nie trzeba się zdecydować, ale najgorsze jest to it doesn’t work jak czasami, nie dostanie przedłużony Java 8 konkretną wersję z JPA 2.6. Ale najwyraźniej JPA 2.7 będzie działać.

Więc można wyprowadzić kilka alternatywnych rozwiązań:

  • Wyłącz populację leniwe
  • Pobyt z Java 7
  • Odczekaj JPA 2.7
  • wystarczy skopiować kolekcję, na przykład
    List<ElementParameter> workList=new ArrayList<>(elementParameters);
    Ten workList będzie wspierać wszystkie operacje Collection & Stream
+0

Dzięki, będę korzystać z 4 metody, lista coping do nowej listy wygląda najlepiej. – simo