问题描述
我尝试在DAO中使用 parallelStream()
使用Spring @Transactional
注释并解决问题:
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) {
...
}
工作正确:
@Transactional
public void processCollection(Collection<Object> objects) {
objects.stream()
.forEach(this::processOne); //work correctly
}
@Transactional
public void processOne(Object o) {
...
}
例外:
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)
我如何使用 @Transactional
注释方法由 parallelStream()
?
How can I use @Transactional
annotated methods by parallelStream()
?
更新
为什么会发生这种情况
但我希望Spring 4支持java 8可以为此提供一些解决方案。有什么想法吗?
UpdateWhy this happen Spring transaction manager and multithreadingBut I hope spring 4 with java 8 support can provide some solution for this. Any ideas?
推荐答案
好吧,我猜了几个猜测:
Well, I have a guess consists of several guesses:
- 您的会话管理策略为
每线程会话
; - <$ c您在示例中写的$ c> Object 实际上是一些使用延迟加载的实体;
-
processOne()
方法使用懒惰加载的实体属性; - 由于第一点,为
parallelStream()
启动的线程没有会话可用(可能在ThreadLocal
中,不记得技术上会话如何绑定到线程);
- 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:
- 删除所有延迟加载并尝试
parallelStream()
再次; - 如果成功,则必须在执行
parallelStream()$之前完全加载实体c $ c>。
- Remove all lazy loading and try
parallelStream()
again; - If that succeeds, you'll have to load the entities completely before performing
parallelStream()
.
另一种方法:在执行 parallelStream()之前从会话中分离所有列表元素
。
虽然Marko在评论中写道, Session
不是线程安全的,这意味着你必须通过删除延迟加载或从会话中分离所有实体来摆脱 Session
的使用。
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.
这篇关于带有spring注释方法的Java .parallelStream()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!