75

これが私を困惑させたものです。基本的な Hibernate DAO 構造を実装しようとしていますが、問題があります。

重要なコードは次のとおりです。

int startingCount = sfdao.count();
sfdao.create( sf );
SecurityFiling sf2 = sfdao.read( sf.getId() );
sfdao.delete( sf );
int endingCount = sfdao.count();

assertTrue( startingCount == endingCount );
assertTrue( sf.getId().longValue() == sf2.getId().longValue() );
assertTrue( sf.getSfSubmissionType().equals( sf2.getSfSubmissionType() ) );
assertTrue( sf.getSfTransactionNumber().equals( sf2.getSfTransactionNumber() ) );

sf の値を sf2 の対応する値と比較しようとしている 3 番目の assertTrue で失敗します。例外は次のとおりです。

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)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:40)
4

14 に答える 14

69

問題は、分離されたオブジェクトのコレクションにアクセスしようとしていることです。コレクションに現在のセッションにアクセスする前に、オブジェクトを再アタッチする必要があります。あなたはそれを行うことができます

session.update(object);

lazy=false休止状態の遅延初期化機能を捨てているため、使用は良い解決策ではありません。の場合lazy=false、オブジェクトが要求されると同時にコレクションがメモリにロードされます。これは、1000 個のアイテムを含むコレクションがある場合、それらにアクセスするかどうかに関係なく、すべてがメモリに読み込まれることを意味します。そして、これは良くありません。

問題、考えられる解決策、およびこのように実装されている理由について説明しているこの記事をお読みください。また、セッションとトランザクションを理解するには、この他の記事を読む必要があります。

于 2010-09-03T12:15:43.520 に答える
15

これは通常、所有している Hibernate セッションが既に閉じられていることを意味します。次のいずれかを実行して修正できます。

  1. この問題を引き起こしているオブジェクトが何であれ、使用しますHibernateTemplate.initialize(object name)
  2. lazy=falsehbm ファイルで使用します。
于 2008-12-06T14:51:40.157 に答える
10

私の記事を参照してください。同じ問題(LazyInitializationException)があり、最終的に思いついた答えは次のとおりです。http://community.jboss.org/wiki/LazyInitializationExceptionovercome
lazy
= falseを設定することは答えではありません。すべてを一度にロードできますが、それは必ずしも良いとは限りません。例:
1レコードテーブルA参照:
5レコードテーブルB参照:
25レコードテーブルC参照:
125レコードテーブルD
...
など。これは、問題が発生する可能性がある一例にすぎません。
-ティム・サビン

于 2011-02-16T20:05:51.333 に答える
7

JPA アノテーションで hibernate を使用している場合、これは便利です。サービス クラスには、@PersistenceContext を持つエンティティ マネージャーのセッターが必要です。これを @PersistenceContext(type = PersistenceContextType.EXTENDED) に変更します。その後、どこからでも遅延プロパティにアクセスできます。

于 2010-09-26T13:50:21.107 に答える
4

遅延読み込みを使用している場合は、メソッドに注釈を付ける必要があります

@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)ステートレス セッション EJB の場合

于 2010-08-16T00:17:34.867 に答える
3

このエラーも発生しました。この問題を解決するために、Hibernate マッピング ファイルにlazy=falseを追加しました。

別のクラス B をロードするセッション内にクラス A があったようです。クラス B のデータにアクセスしようとしていますが、このクラス B はセッションから切り離されています。

このクラス B にアクセスするには、クラス A の Hibernate マッピング ファイルで lazy=false 属性を指定する必要がありました。例えば、

     <many-to-one name="classA" 
                 class="classB"
                 lazy="false">
        <column name="classb_id"
                sql-type="bigint(10)" 
                not-null="true"/>
    </many-to-one>  
于 2010-09-03T08:39:00.917 に答える
2

If you know about the impact of lazy=false and still want to makes it as default (e.g., for prototyping purposes), you can use any of the following:

  • if you are using XML configuration: add default-lazy="false" to your <hibernate-mapping> element
  • if you are using annotation configuration: add @Proxy(lazy=false) to your entity class(es)
于 2010-11-04T02:08:02.340 に答える
2

さて、ついに私が怠けていた場所を見つけました。私は、各 DAO メソッドをトランザクションでラップする必要があるという誤った考えを持っていました。ひどく間違っている!私は教訓を学びました。すべての DAO メソッドからすべてのトランザクション コードを収集し、アプリケーション/マネージャー レイヤーで厳密にトランザクションをセットアップしました。これにより、すべての問題が完全に解決されました。データは必要に応じて適切に遅延ロードされ、コミットするとラップアップされて閉じられます。

人生は良いです... :)

于 2009-01-07T23:17:42.490 に答える
2

あなたのDAOだけがセッションを使用しているようです。したがって、新しいセッションが開かれ、DAO メソッドへの呼び出しごとに閉じられます。したがって、プログラムの実行は次のように再開できます。

// open a session, get the number of entity and close the session
int startingCount = sfdao.count();

// open a session, create a new entity and close the session
sfdao.create( sf );

// open a session, read an entity and close the session
SecurityFiling sf2 = sfdao.read( sf.getId() );

// open a session, delete an entity and close the session
sfdao.delete( sf );

etc...

デフォルトでは、エンティティのコレクションと関連付けはレイジーです。これらはデータベースからオンデマンドで読み込まれます。したがって:

sf.getSfSubmissionType().equals( sf2.getSfSubmissionType() )

は、データベースからの新しい読み込みを要求し、エンティティの読み込みに関連付けられたセッションが既に閉じられているため、例外をスローしています。

この問題を解決するには、次の 2 つの方法があります。

  • すべてのコードを囲むセッションを作成します。したがって、2 番目のセッションを開かないように DAO コンテンツを変更することを意味します。

  • セッションを作成し、アサーションの前にエンティティをこのセッションに更新 (つまり再接続) します。

    session.update(オブジェクト);

于 2012-05-03T11:39:40.900 に答える
1

レイジーフィールドにはHibernate.initializeを使用します

于 2011-08-03T14:15:16.637 に答える
1

私はピコが彼の応答でhbmファイルがあることを意味していると思います. Tax.java というファイルがあります。マッピング情報は hbm (=hibernate mapping) ファイルに保存されます。class タグには、 lazyというプロパティがあります。そのプロパティを true に設定します。次の hbm の例は、lazy プロパティをfalseに設定する方法を示しています。

「id ...」

代わりに注釈を使用している場合は、休止状態のドキュメントを参照してください。 http://docs.jboss.org/hibernate/stable/annotations/reference/en/html_single/

お役に立てば幸いです。

于 2010-07-26T13:07:50.523 に答える
1

Hibernate セッションを手動で管理している場合は、以下の sessionFactory.getCurrentSession() および関連ドキュメントを参照してください。

http://www.hibernate.org/hib_docs/v3/reference/en/html/architecture-current-session.html

于 2008-12-09T02:17:15.903 に答える