Java .parallelStream() with spring annotated methods
Solution 1
Well, I have a guess consists of several guesses:
- You have session management policy as
session-per-thread
; Object
you wrote in example is in fact some entity that uses lazy loading;processOne()
method uses entity properties that are loaded lazily;- Because of first point, threads, started for
parallelStream()
has no session available (probably inThreadLocal
, don't remember how technically sessions are bound to threads);
That altogether causing the problem you have. The behavior looks quite strange to me, so I suggest to do the following:
- Remove all lazy loading and try
parallelStream()
again; - If that succeeds, you'll have to load the entities completely before performing
parallelStream()
.
Alternative way to go: detaching all list elements from session before doing parallelStream()
.
Although as Marko wrote in comments, Session
is not thread-safe, so that means you have to get rid of Session
usage either by removing lazy loading, or by detaching all entities from session.
Solution 2
The problem is not with parallel stream. In spring transaction is created using AOP.
When your processCollection method is executed spring create a proxy object of this and transaction is started.
Calling another method in same class, spring will not run that method in New transaction even if you specified @Transaction .
To get it run move that method process() to new service and then execute your problem. Your program will work fine.
VladS
Updated on June 25, 2022Comments
-
VladS almost 2 years
I try using the
parallelStream()
in DAO with Spring@Transactional
annotations and get so problem:@Transactional public void processCollection(Collection<Object> objects) { objects.parallelStream() .forEach(this::processOne); //throw exception } @Transactional public void processOne(Object o) { ... }
Works correct:
@Transactional public void processCollection(Collection<Object> objects) { objects.stream() .forEach(this::processOne); //work correctly } @Transactional public void processOne(Object o) { ... }
Exception:
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)
How can I use
@Transactional
annotated methods byparallelStream()
?Update Why this happen Spring transaction manager and multithreading But I hope spring 4 with java 8 support can provide some solution for this. Any ideas?
-
Marko Topolnik about 10 yearsHibernate's session is not thread-safe. The only option is detachment.
-
Alexey Malev about 10 years@MarkoTopolnik Thanks Marko, didn't know that.