0

Hibernateでいくつかのエンティティを読んでいます:

Criteria criteria = session.createCriteria(…);
List<Entity> list = (List<Entity>) criteria.list();

今、私はこのリストを繰り返し処理しており、 a 内のすべてのオブジェクトを に送信したいと考えていRunnableますExecutor。したがって、私はを使用しRunnableBeanます。

for (Entity entity : list) {
    IRunnableBean runnableBean = (IRunnableBean) 
        applicationContext.getBean("myRunnableBean", IRunnableBean.class);
    runnableBean.setEntity(entity);
    executor.execute(runnableBean);
}

は次のRunnableBeanようになります。

RunnableBean implements IRunnableBean {

    // Setter

    @Transactional
    void run() {
        entity.getMyCollection();
    }
}

コレクションにアクセスすると、org.hibernate.LazyInitializationException( no session or session was closed) が表示されます。

Spring のログを見ると、トランザクション メソッドrun()が正しく追加されていることがわかります。私は何を間違っていますか?

4

3 に答える 3

2

SpringのOpenSessionInViewFilterを使用していると思います。その場合、この動作が予想されます。フィルタは、データベース接続を、では使用できないスレッドローカルコンテキストに配置しますRunnableBean

myCollection熱心にロードされていないため、Springは内部のデータベース接続にアクセスできRunnableBeanず、ロードできません。必要がある:

  • で囲んでいるセッションラッパーを作成しますRunnableBean
  • オブジェクトを渡す代わりにコレクションのIDをRunnableBean渡し、コレクションを内部にロードしますRunnableBean

または、エンティティをmyCollection熱心にロードするようにすることもできますが、これにより、ロードプロセス全体が遅くなります。

于 2012-11-08T14:22:31.850 に答える
0

また、トランザクションを保持するスレッドとは異なるスレッドで実行されるため、Bean でトランザクションを使用できないと (@mindas のように) 推測します。私の経験によると、Spring はスレッド ローカルも使用してスコープ指定されたプロキシを解決するため、これらは非同期で実行される Bean でも機能しません。

非同期呼び出しは長時間実行されるため (そうでなければ、なぜ非同期呼び出しを使用するのでしょうか?)、これによりトランザクションがブロックされたり、タイムアウトが発生したりするため、基本的には、非同期方式でトランザクションを必要とするロジックを実行しないようにします。

jpa の基準 API は、特定のクエリに対してのみリレーションを積極的にフェッチする方法を提供します。多分それは選択かもしれませんか?それ以外の場合、コレクションの size() メソッドにアクセスすると、コレクションが初期化されます。

于 2012-11-08T15:00:20.023 に答える
0

for既に記述されているループ内に次の行を追加するだけです。

Hibernate.initialize(entity.getMyCollection());

これは、コレクションを遅延ではなく熱心にロードすることLazyInitializationExceptionです。

于 2012-11-08T14:40:00.970 に答える