Java .parallelStream() mit Feder annotierten Methoden
Ich versuche, mithilfe der parallelStream()
in DAO mit Spring @Transactional
Anmerkungen und bekommen so problem:
@Transactional
public void processCollection(Collection<Object> objects) {
objects.parallelStream()
.forEach(this::processOne); //throw exception
}
@Transactional
public void processOne(Object o) {
...
}
Funktioniert richtig:
@Transactional
public void processCollection(Collection<Object> objects) {
objects.stream()
.forEach(this::processOne); //work correctly
}
@Transactional
public void processOne(Object o) {
...
}
Ausnahme:
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)
Wie kann ich @Transactional
annotierte Methoden von parallelStream()
?
Update
Warum dies geschehen Spring transaction manager und multithreading
Aber ich hoffe, spring 4 mit java-8-Unterstützung kann auch eine Lösung für dieses. Irgendwelche Ideen?
- Eine triviale Frage, aber bekommt man die gleiche Fehlermeldung, wenn Sie stream().parallel()?
- Ja, ich habe das gleiche problem mit stream().parallel()
- stackoverflow.com/questions/16835974/...
- Danke Evgeni, ich verstehe, warum dies geschieht. Arbeit um für diese interessant ist.
- Ich Frage mich, warum möchten Sie die @Transactional auf processCollection, wenn Sie wollen, um es zum laufen parallel.
- Es ist nur Beispiel, Was passiert, wenn es '@Cacheable' Instanz von '@Transactional' ? Cache wird für die Arbeit nur ein thread, wie ich Sie verstehe..
Du musst angemeldet sein, um einen Kommentar abzugeben.
Gut, ich habe eine Vermutung besteht aus mehreren Vermutungen:
session-per-thread
;Object
Sie schrieb im Beispiel ist in der Tat eine Entität, die verwendet lazy loading;processOne()
Methode benutzt entity-Eigenschaften, die geladen sind faul;parallelStream()
hat keine Sitzung zur Verfügung (wahrscheinlich inThreadLocal
, weiß nicht, wie technisch-Sitzungen gebunden sind, threads);Dass insgesamt verursacht das problem, das Sie haben. Das Verhalten sieht ganz seltsam für mich, so schlage ich vor, Folgendes zu tun:
parallelStream()
wieder;parallelStream()
.Alternativen Weg zu gehen: abnehmen werden alle Listen-Elemente aus der Sitzung vor
parallelStream()
.Obwohl, wie Marko schrieb in den Kommentaren,
Session
ist nicht thread-safe ist, also das bedeutet, dass Sie haben, um loszuwerdenSession
Nutzung entweder durch entfernen lazy loading, oder trennen Sie alle Einheiten aus der Sitzung.Das problem ist nicht mit parallel-stream .Im Frühjahr Transaktion erstellt wird, mithilfe von AOP.
Wenn Ihr processCollection Methode ausgeführt wird Frühling erstellen Sie eine proxy-Objekt und Transaktion gestartet.
Aufruf anyother Methode in der gleichen Klasse ,wird der Frühling nicht ausführen, die Methode in Neue Transaktion, auch wenn Sie angegeben @Transaktion .
Um es auszuführen, bewegen, die Methode process() auf neue service-und führen Sie dann Ihr problem.Ihr Programm wird gut funktionieren.