0

私の問題は簡単です。アプリケーションが Tomcat にロードされたときに、データベースからいくつかのデータにアクセスしたいと考えています。その時点で何かを行うには、@PostConstruct (適切に機能します) を使用します。

ただし、その方法では、DB に 2 つの個別の接続を作成します。1 つはエンティティのリストを取得するためのもので、もう 1 つはそれらを共通のライブラリに追加するためのものです。2 番目のステップは、いくつかの遅延読み込み関連付けを解決するための舞台裏のクエリを意味します。コード スニペットは次のとおりです。

@Override
@PostConstruct
public void populateLibrary() {
// query for the Book Descriptors - 1st query works!!!
List<BookDescriptor> bookDescriptors= bookDescriptorService.list();

Session session = sessionFactory.openSession();
Transaction transaction = null;
try {
    transaction = session.beginTransaction();

        // resolving some lazy-loading associations - 2nd query fails!!!
    for (BookDescriptor book: bookDescriptors) {
         library.addEntry(book);
    }

    transaction.commit();
} catch (HibernateException e) {

    transaction.rollback();
    e.printStackTrace();
} finally {
    session.close();
}
}

コメントに書いたように、最初のクエリは機能しますが、2 番目のクエリは失敗します。失敗すると次のようになります。

org.hibernate.LazyInitializationException: could not initialize proxy - no Session
at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:86)
at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:140)
at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:190)
at com.freightgate.domain.SecurityFiling_$$_javassist_7.getSfSubmissionType(SecurityFiling_$$_javassist_7.java)
at com.freightgate.dao.SecurityFilingTest.test(SecurityFilingTest.java:73)

トランザクションを明示的に開いて閉じたので、これは非常に奇妙です。ただし、最初のクエリがどのように機能するかの詳細を調べると、舞台裏でセッションが AbstractLazyInitializer クラスにバインドされているように見えます。

@Transactional(readOnly = true) で注釈が付けられた別のサービス クラスに for ループから機能を抽象化することで、問題を解決しました。それでも、ここに投稿したアプローチが失敗する理由については困惑しています。

誰かがヒントを持っているなら、私はそれらを聞いてとてもうれしいです.

4

1 に答える 1

1

最初のセッションでエンティティをロードし、このセッションを閉じてから新しいセッションを開き、エンティティのコレクションを遅延ロードしようとします。それはうまくいきません。

遅延読み込みが機能するには、エンティティが開いているセッションに接続されている必要があります。別のセッションを開くだけでは、この新しいセッションにアタッチされる前にロードしたエンティティは作成されません。その間に、他のトランザクションがデータベースを根本的に変更した可能性があり、エンティティはもはや存在できませんでした...

最善の解決策は、あなたがしたことです。すべてを単一のトランザクション サービスにカプセル化します。最初のサービスを呼び出す前にトランザクションを開くこともできますが、Spring が宣言的にトランザクションを処理するのに、なぜトランザクションをプログラムで処理するのでしょうか?

于 2012-12-16T15:25:32.467 に答える