52

遅延初期化を使用したい顧客向けのプロジェクトに取り組んでいます。クラスをデフォルトの遅延読み込みモードでマッピングすると、常に「遅延初期化例外」が発生します。

@JoinTable(name = "join_profilo_funzionalita", joinColumns = {@JoinColumn(name =    "profilo_id", referencedColumnName = "profilo_id")}, inverseJoinColumns = {@JoinColumn(name = "funzionalita_id", referencedColumnName = "funzionalita_id")})
//@ManyToMany(fetch=FetchType.EAGER) - no exceptions if uncommented
@ManyToMany 
private Collection<Funzionalita> funzionalitaIdCollection;

このエラーを回避するために JPA クラスを使用する標準パターンはありますか?

スニペットは大歓迎です。お時間をいただきありがとうございます。

4

9 に答える 9

60

Hibernate 4.1.6 は最終的にこの問題を解決します: https://hibernate.atlassian.net/browse/HHH-7457

hibernate-property hibernate.enable_lazy_load_no_trans=true を設定する必要があります

春にそれを行う方法は次のとおりです。

<bean id="entityManagerFactory"
      class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="dataSource" ref="myDataSource"/>
    <property name="packagesToScan" value="com.mycompany.somepackage"/>
    <property name="jpaVendorAdapter" ref="hibernateVendorAdapter"/>
    <property name="jpaDialect" ref="jpaDialect"/>
    <property name="jpaProperties">
        <props>
            <prop key="hibernate.enable_lazy_load_no_trans">true</prop>
        </props>
    </property>
</bean>

出来上がり。これで、休止状態セッションの外でドメインモデルをナビゲートする際に LazyInitializationException について心配する必要がなくなりました (「JPA で言えば永続化コンテキスト」)。

于 2012-08-11T09:10:05.043 に答える
17

プロパティをプリフェッチするには多くの方法があるため、セッションが閉じられた後も存在します。

  1. 適切なゲッターを呼び出します。フィールドが Bean にフェッチされた後、セッションが閉じられた後もそこにあります。
  2. EJBQL query でフィールドを初期化して、JOIN FETCHキーワードを探すことができます。
  3. それをサポートする Hibernate バージョンを使用している場合は、AvailableSettings.ENABLE_LAZY_LOAD_NO_TRANS を有効にします。

これらの解決策を試すと、いくつかの問題が発生する可能性があります。

  1. ゲッターの呼び出しは、JIT コンパイラーによって最適化される場合があります (これには時間がかかる場合があります)。
  2. あなたがしようとしているエンティティはJOIN FETCH、リストを含む複数の「多くの」関係を介してリンクされている可能性があります。この場合、結果のクエリはあいまいな結果を返し、Hibernate は単一のクエリでデータをフェッチすることを拒否します。
  3. AvailableSettings.ENABLE_LAZY_LOAD_NO_TRANS に関連する興味深いバグが既に 1 つあります。休止状態の人が言うように、さらに多くのことがあります:注: これはトランザクションの外で発生する可能性があり、安全ではありません。注意して使用してください。あなたはほとんど一人でいます。

最善の方法は、JOIN FETCH最初に試すことです。それでもうまくいかない場合は、ゲッターのアプローチを試してください。それが実行時に JIT コンパイラーによって台無しにされた場合は、結果をpublic static volatile Object.

または、休止状態の使用を停止します...

于 2009-05-10T11:45:14.033 に答える
16

hibernate.enable_lazy_load_no_trans接続がリークするため、Hibernate 4.1.7 より前のバージョンは使用しないでください。https://hibernate.onjira.com/browse/HHH-7524を参照してください。

于 2012-09-06T21:20:58.960 に答える
8

LazyInitializationException は、hibernate セッションが閉じた後、またはオブジェクトがセッションから切り離された後にコレクションを呼び出していることを意味します。

オブジェクトを再アタッチしてセッションを休止するか、コレクションを呼び出す場所を変更するか、セッションが閉じられる場所の境界を上位レイヤーに移動する必要があります。

于 2009-03-23T02:53:57.740 に答える
5

OpenSessionInViewは、この問題に対処するための1つのパターンです。ここにいくつかの情報:

http://www.hibernate.org/43.html

このパターンを実装するときは注意が必要であり、その影響を理解する必要があります。ビューでレイジーアソシエーションをナビゲートするたびに、データをロードするために別のSQLクエリが実行されます。これらのSQLクエリの数とサイズが小さいようなユースケースの場合、これは問題にならない可能性があります。少なくともログ設定を調整して、データをロードするためにHibernateがバックグラウンドで「魔法のように」実行しているクエリの種類を確認できるようにしてください。

また、作成しているアプリケーションの種類も考慮してください。リモーティングを扱っていない場合(WebサービスやAJAXベースのWebクライアントがない場合)、OSIVは非常にうまく機能する可能性があります。ただし、リモーティングシリアライザーがオブジェクトグラフ全体を調べ始めると、ばかげた数のSQLクエリがトリガーされ、DBサーバーとアプリサーバーが機能しなくなる可能性があります。

于 2009-02-23T18:19:48.577 に答える
4

コレクションを使用していて、遅延読み込みで初期化する場合は、セッションを閉じる前にそのコレクションを使用します。その後セッションが終了した場合、デフォルトで lazy が試行されるため、使用する場合は lazyinitializeException が発生します。

于 2011-11-02T12:39:14.683 に答える