2014-04-24 14 views
11

provo utilizzando il parallelStream() in DAO con la Primavera @Transactional annotazioni e riceverai problema:Java .parallelStream() con i metodi di primavera annotato

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

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

Opere corretto:

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

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

Eccezione:

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) 

Come è possibile utilizzare i metodi annotati @Transactional entro il parallelStream()?

Aggiornamento Perchè questo accada Spring transaction manager and multithreading ma spero molla 4 con Java 8 supporto in grado di fornire una soluzione per questo. Qualche idea?

+0

Una domanda banale, ma si ottiene lo stesso errore se si utilizza stream(). Parallel()? –

+0

Sì, ho lo stesso problema con stream(). Parallel() – VladS

+0

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

risposta

5

Beh, ho una supposizione consiste di diverse ipotesi:

  • Avete politica di gestione sessione come session-per-thread;
  • Object che hai scritto nell'esempio è in effetti qualche entità che utilizza il caricamento lazy;
  • processOne() utilizza le proprietà dell'entità caricate pigramente;
  • A causa del primo punto, thread, avviato per parallelStream() non è disponibile alcuna sessione (probabilmente in ThreadLocal, non ricordo come tecnicamente le sessioni siano legate ai thread);

Tutto ciò causa il problema che si ha. Il comportamento mi sembra abbastanza strano, quindi suggerisco di fare quanto segue:

  • Rimuovere tutto il carico pigro e provare di nuovo parallelStream();
  • Se ciò riesce, sarà necessario caricare completamente le entità prima di eseguire parallelStream().

Modo alternativo per andare: scollegare tutti gli elementi della lista dalla sessione prima di fare parallelStream().

Sebbene Marko abbia scritto nei commenti, Session non è thread-safe, pertanto è necessario eliminare l'utilizzo di Session rimuovendo il caricamento lazy o scollegando tutte le entità dalla sessione.

+4

La sessione di Hibernate non è thread-safe. L'unica opzione è il distacco. –

+0

@ MarkoTopolnik Grazie Marko, non lo sapevo. –

Problemi correlati