Java .parallelStream() with spring annotated methods

若如初见. 提交于 2019-12-04 10:23:28

问题


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 by parallelStream()?

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?


回答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 in ThreadLocal, 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.




回答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 anyother 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.



来源:https://stackoverflow.com/questions/23266866/java-parallelstream-with-spring-annotated-methods

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!