Java .parallelStream() と Spring アノテーション付きメソッド 質問する

Java .parallelStream() と Spring アノテーション付きメソッド 質問する

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

おすすめ記事