parallelStream()
Spring@Transactional
アノテーションを使用して DAO を使用しようとすると、次のような問題が発生します。
@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()
?
アップデートなぜこんなことが起こるのかSpring トランザクション マネージャーとマルチスレッドしかし、Java 8 をサポートする Spring 4 が、この問題に対する何らかの解決策を提供してくれることを期待しています。何かアイデアはありますか?
ベストアンサー1
さて、私はいくつかの推測から成る推測を持っています:
- セッション管理ポリシーは次のとおりです
session-per-thread
。 Object
例に書いたものは、実際には遅延読み込みを使用するエンティティです。processOne()
メソッドは遅延ロードされるエンティティ プロパティを使用します。- 最初のポイントである、 に開始されたスレッドには
parallelStream()
利用可能なセッションがありません (おそらく でThreadLocal
、技術的にセッションがスレッドにどのようにバインドされるかは覚えていません)。
これらが、あなたが抱えている問題の原因です。この動作は私にとっては非常に奇妙に思えるので、次の操作を行うことをお勧めします。
- すべての遅延読み込みを削除して
parallelStream()
再試行してください。 - それが成功した場合は、 を実行する前にエンティティを完全にロードする必要があります
parallelStream()
。
別の方法: を実行する前に、すべてのリスト要素をセッションから切り離しますparallelStream()
。
Marko がコメントで書いたように、スレッドセーフではないため、遅延読み込みを削除するか、すべてのエンティティをセッションから切り離すことによって、使用Session
をなくす必要があります。Session