1. ホーム
  2. ハイバーネート

LazyInitializationException: ロールのコレクションを遅延して初期化できませんでした。

2022-02-22 05:31:05

からの転載です。 https://blog.csdn.net/lch_2016/article/details/81051685

ハイバーネートのレイジーローディングとは何ですか?遅延ロードはいつ使用するのですか?なぜ遅延ロードを使用するのですか? 遅延ロードの解決策

から取得しました。 https://www.cnblogs.com/cornucopia/articles/4541621.html

から取得した。 https://blog.csdn.net/qq_21033663/article/details/51236009

要約すると

いわゆる遅延ロード(lazy)とは、遅延ロード、ディレイドローディングのことです。



レイジーローディングはいつ使うの?遅延ロードを使いたいときしか答えられません。



なぜレイジーローディングを使うべきかというと、アクセスしたいデータ量が膨大で、キャッシュを使うのが明らかに適切でない場合です。



メモリ容量に限りがあるため、並行処理やシステムリソースの消費を抑えるため。

必要な時だけデータを読み込ませる、そこでレイジーローディングを利用します

lazy には、true、false、extra の 3 つのプロパティがあります。



true]:デフォルト値が採用されており、このコレクションが呼び出されて中の要素オブジェクトを取得したときのみ、その要素オブジェクトをロードするためのクエリ文が発行されることを意味します。 



     コレクション要素のデータ 



[false]:レイジーローディング機能を削除します。つまり、オブジェクトがロードされている間に、関連するコレクションのデータをロードするために2番目のクエリステートメントを発行します。 

hibernate は、コレクションの size/contains メソッドを呼び出すときにコレクション全体をロードせず、代わりにスマート SQL 文を発行して必要な値を取得し、本当に必要なときにのみコレクション要素のすべてをロードするクエリーを発行します。 オブジェクトのデータです。

解決策

1) 遅延ロードを使用しない: 子テーブル設定ファイルのlazy属性をfalseに変更し、特定のカスケード関係で遅延ロードを使用しない



 2) フィルタを使用して、ページの結果を取得した後までセッションを閉じるステップを延期します。これは、springのOpenSessionInViewFilter(これはフィルターです)を使用することで可能です。この方法は、サーブレットフィルタにセッションを与えることで、 リクエストが来るたびにセッションを開き、レスポンスが終了したときにだけセッションを閉じるというものです。



 3) データベースキャッシュから必要なサブテーブルデータをjvmメモリに手動でロードする。たとえば、Classroom は Student エンティティクラスと一対多の関係になっています (多対多も適用されます)。

元記事

 いわゆるレイジーローディング(lazy)とは、遅延ローディング、ディファードローディングのことです。2つ以上のテーブルがhibernateを使用してカスケード関係を管理する場合、あるテーブルがjvmメモリにロードされると、その関連テーブルをデータベースキャッシュに一時的に保存し、関連テーブルデータが必要になったときにjvmメモリにロードすることができます。レイジーローディングの仕組みにより、メモリ上の不要なオーバーヘッドを削減し、プログラムのパフォーマンスを向上させることができます。

    レイジーローディングを使用する場合、セッションを閉じると、データベースへの接続が切断され、子テーブルデータにアクセスしたい場合、子テーブルデータはデータベースキャッシュに格納され、接続が閉じられるため、子テーブルデータにアクセスすると、LazyInitializationExceptionがスローされることに注意してください。

     回避策

    1) 遅延ロードを使用しない:子テーブル設定ファイルのlazy属性をfalseに変更し、特定のカスケード関係で遅延ロードを使用しない。

     <many-to-one name="parent" class="ParrentClass" column="parentId" lazy="false"></many -to-one>  

    注:多対多の場合も同様です

    または、どの親テーブルに対しても遅延ロードを使用しないように設定すると、子テーブル全体に対して遅延ロードが使用されなくなる

    <class name="ChildClass" table="childTable" lazy="false">

    2) フィルタを使用して、ページの結果を取得した後までセッションを閉じるステップを延期します。これは、spring の OpenSessionInViewFilter (これはフィルターです) を使って行うことができます。

    web.xmlに設定を追加します。

    <filter>  



       <filter-name>OpenSessionInViewFilter</filter-name>  



    <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>  



    </filter>  



    <filter-mapping>  



       <filter-name>OpenSessionInViewFilter</filter-name>  



       <url-pattern>*.action</url-pattern>  



    </filter-mapping>  

    3) データベースキャッシュから必要なサブテーブルのデータをjvmメモリに手動でロードする。例えば、Classroom は Student エンティティクラスと一対多の関係 (多対多も適用される)、すなわち、以下のような関係を持っています。

public クラスルーム { <未定義

    private Set<Student> students;

    .........

}

daoレイヤーには

List<ClassRoom> list = セッション取得結果セット操作

for (教室 classroom : リスト) { <未定義



    Hibernate.initialize(classroom.getStudents()); // 教室エンティティに対応するStudentコレクションをループして、jvmメモリにパッチします。

}

session.close()を実行します。

メソッドの比較。最初の方法は単純で残酷です。利点は、読み込み遅延の例外が発生しないため、あまり気にならないことです。欠点は、関連するすべてのデータが毎回jvmメモリに読み込まれるため、メモリリソースを消費することです。2番目のメソッドは、一般的にJavaWebで使用され、利点は、合理的にロード時間を決定し、必要に応じてロードするかどうか、欠点は、J2SEプロジェクトのために、J2EEで使用することができます 第三の方法は、ロードするときに柔軟に制御の利点は、欠点は、追加のコードを追加することとサブ表のデータをロードする必要性がセッションが閉じられる前にjvmメモリにそれを引くことを忘れて、LazyInitializationExceptionが投げられることになります。