2014-04-24 14 views
11

staram pomocą parallelStream() w DAO z Wiosna @Transactional adnotacji i uzyskaj problem:Java .parallelStream() ze sprężyną odnotowany metody

@Transactional 
public void processCollection(Collection<Object> objects) { 
    objects.parallelStream() 
      .forEach(this::processOne); //throw exception 
} 

@Transactional 
public void processOne(Object o) { 
    ... 
} 

Works poprawne:

@Transactional 
public void processCollection(Collection<Object> objects) { 
    objects.stream() 
      .forEach(this::processOne); //work correctly 
} 

@Transactional 
public void processOne(Object o) { 
    ... 
} 

Wyjątek:

org.hibernate.HibernateException: No Session found for current thread 
org.springframework.orm.hibernate4.SpringSessionContext.currentSession(SpringSessionContext.java:106) 
org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:978) 

Jak używać metod opatrzonych komentarzem @Transactional przez parallelStream()?

Aktualizacja Dlaczego tak się stało Spring transaction manager and multithreading Ale mam nadzieję, że sprężyna 4 z Java 8 wsparcie może zapewnić pewne rozwiązanie tego problemu. Jakieś pomysły?

+0

Pytanie trywialne, ale czy otrzymasz ten sam błąd, jeśli używasz strumienia(). Parallel()? –

+0

Tak, mam ten sam problem ze strumieniem(). Parallel() – VladS

+0

http://stackoverflow.com/questions/16835974/spring-transaction-manager-and-multithreading –

Odpowiedz

5

Otóż mam przypuszczenie składa się z kilku domysły:

  • Masz politykę zarządzania sesji jako session-per-thread;
  • Object napisałeś w przykładzie to w rzeczywistości jakaś jednostka, która używa leniwego ładowania;
  • processOne() metoda wykorzystuje właściwości obiektu ładowane leniwie;
  • Z powodu pierwszego punktu wątki rozpoczęte dla parallelStream() nie mają dostępnej sesji (prawdopodobnie w ThreadLocal, nie pamiętam, jak technicznie sesje są powiązane z wątkami);

To wszystko powoduje problem, który masz. To zachowanie wydaje mi się dość dziwne, więc sugeruję wykonać następujące czynności:

  • Usuń wszystkie luźne ładowanie i spróbuj ponownie parallelStream();
  • Jeśli się to uda, będziesz musiał załadować je całkowicie przed wykonaniem parallelStream().

Alternatywny sposób postępowania: odłączanie wszystkich elementów listy od sesji przed wykonaniem parallelStream().

Chociaż tak jak pisał Marko w komentarzach, Session nie jest bezpieczny dla wątków, więc oznacza to, że musisz pozbyć się użycia Lprzez usunięcie leniwego ładowania lub przez odłączenie wszystkich elementów od sesji.

+4

Sesja Hibernate nie jest wątkowa. Jedyną opcją jest odłączenie. –

+0

@MarkoTopolnik Dzięki Marko, nie wiedziałem o tym. –

Powiązane problemy