Hibernateの遅延読み込みとは何ですか?


178

Javaの遅延読み込みとは何ですか?プロセスがわかりません。誰かが遅延読み込みのプロセスを理解するのを手伝ってくれる?

回答:


268

親がいて、その親に子供たちのコレクションがあるとします。Hibernateが子を「遅延ロード」できるようになりました。つまり、親をロードするときに、実際にはすべての子をロードしません。代わりに、要求されたときにそれらをロードします。これを明示的に要求することもできますが、これははるかに一般的です。子にアクセスしようとすると、Hibernateがそれらを自動的にロードします。

多くの場合、子は必要ないため、ロードされないため、遅延ロードはパフォーマンスを大幅に向上させるのに役立ちます。

また、n + 1問題にも注意してください。コレクションにアクセスすると、Hibernateは実際にはすべての子をロードしません。代わりに、各子を個別にロードします。コレクションを反復するとき、これはすべての子に対してクエリを引き起こします。これを回避するために、たとえばparent.getChildren()。size()を呼び出すことによって、休止状態をだましてすべての子を同時にロードすることができます。


5
または、Hibernate.initialize(parent.getChildren())を使用する必要があります
HakunaMatata 2013

18
「コレクションにアクセスすると...子が個別に読み込まれます」という記述は、実際には完全に不正確です。実際には正反対です。parent.getChildren()を逆参照すると、Hibernateはコレクション内のすべての子を1つのdbクエリでロードします。特別な「特別な遅延」遅延読み込みヒントを使用しない限り。または、コレクションを2次キャッシュにキャッシュし、関連する子もキャッシュしない限り。
Steve Ebersole 14

ああ、スタックオーバーフロー-ベストアンサーはページの下部にあります;-)
ピオトレックフリチュク

76

「遅延読み込み」とは、エンティティに初めて実際にアクセスしたときにのみエンティティが読み込まれることを意味します。

パターンは、このようなものです:

public Entity getEntity() {
    if (entity == null) {
        entity = loadEntity();
    }
    return entity;
}

これは、予備充填/プリロードのコスト節約すべてのあなたのすべての後には、実際には必要ありませんが、事前に大規模なデータセット内のエンティティのすべてのそれらのを。

Hibernateでは、子エンティティのコレクションを遅延ロードするように構成できます。実際の遅延ロードは、その後のメソッド内で行われているPersistentSet「フードの下に」これはHibernateの用途として、エンティティのコレクションを割り当てますSet

例えば

public class Parent {
    private Set<Child> children;

    public Set<Child> getChildren() {
        return children;
    }
}

public void doSomething() {
    Set<Child> children = parent.getChildren(); // Still contains nothing.

    // Whenever you call one of the following (indirectly), 
    // Hibernate will start to actually load and fill the set.
    children.size();
    children.iterator();
}

25

Martin Fowlerは、エンタープライズアプリケーションアーキテクチャのパターンでレイジーロードパターンを次のように定義しています

必要なすべてのデータは含まれていませんが、その取得方法を知っているオブジェクト。

そのため、特定のオブジェクトをロードする場合、関連するパフォーマンスコストを節約するためにすぐに使用できない可能性のある関連オブジェクトを熱心にロードしないようにすることが考えられます。代わりに、関連するオブジェクトは使用時にのみ読み込まれます。

これは、データアクセスとHibernateに固有のパターンではありませんが、そのようなフィールドで特に役立ちます。Hibernateは、1対多の関連付けと単一ポイントの関連付け(1対1および多対1)の遅延読み込みもサポートします。特定の条件下で。遅延相互作用については、Hibernate 3.0リファレンスドキュメントの第19章で詳しく説明しています。


15

デフォルトでは、遅延読み込みはtrueです。遅延読み込みは、選択クエリが実行されたときにデータベースにヒットしないことを意味します。これは、getter関数を待機します。つまり、必要なときに、datbaseからフェッチします。例:あなたはたくさんのおもちゃを持つ子供がいる親です。しかし、現在の問題は、あなたが彼に電話するときはいつでも(私たちはあなたが男の子を持っていると仮定します)、彼はすべてのおもちゃも持ってきます。あなたが彼にいつもおもちゃを持ち歩いてほしくないので、今これは問題です。つまり、根拠となる親であるあなたは、すぐに子供のおもちゃをLAZYと定義します。今、あなたが彼を呼ぶときはいつでも、彼はおもちゃなしであなたのところにやって来るだけです。


11

遅延フェッチは、親オブジェクトのロード中に子オブジェクトをロードするかどうかを決定します。この設定は、親クラスのそれぞれの休止状態マッピングファイルで行う必要があります。 Lazy = true(子を読み込まないことを意味します)デフォルトでは、子オブジェクトの遅延読み込みはtrueです。

これによりgetChild()、親のメソッドを呼び出してアプリケーションで明示的に呼び出されない限り、子オブジェクトが読み込まれないようになります。この場合、hibernateは新しいデータベース呼び出しを発行して子を読み込みますgetChild()になります。

ただし、場合によっては、親が読み込まれるときに子オブジェクトを読み込む必要があります。lazy = falseにするだけで、データベースから親がロードされたときにhibernateが子をロードします。

例:TABLEがある場合?EMPLOYEEはEmployeeオブジェクトにマップされ、Addressオブジェクトのセットを含みます。親クラス:従業員クラス、子クラス:住所クラス

public class Employee { 
private Set address = new HashSet(); // contains set of child Address objects 
public Set getAddress () { 
return address; 
} 
public void setAddresss(Set address) { 
this. address = address; 
} 
} 

Employee.hbm.xmlファイル

<set name="address" inverse="true" cascade="delete" lazy="false"> 
<key column="a_id" /> 
<one-to-many class="beans Address"/> 
</set> 

上記の構成では。If lazy="false":-Employeeオブジェクトをロードすると、そのときに子オブジェクトAddressもロードされ、setAddresss()メソッドに設定されます。employee.getAdress()を呼び出すと、ロードされたデータが返されます。新しいデータベース呼び出しはありません。

次の場合lazy="true":-これがデフォルトの構成です。言及しない場合は、休止状態でlazy = trueを検討してください。子オブジェクトAdressが読み込まれていないEmployeeオブジェクトを読み込むとき。アドレスオブジェクトを取得するには、データベースへの追加の呼び出しが必要です。呼び出すとemployee.getAdress()、その時点でデータベースクエリが起動し、結果が返されます。新鮮なデータベース呼び出し。


このシナリオでは、従業員と住所に親子関係がありません。それは「ハサミ」関係です!
Ram

これは継承ではなく集計です。
リシ

11

素人の言葉では、それはあなたがケーキを作っているようなもので、冷蔵庫から5-10の材料が必要になります。2つのオプションがあります。冷蔵庫からすべての材料を取り出してキッチンの台に置くか、必要なときに必要なアイテムを持ち帰ります。

同様に、eager loadingの場合、Beanとその関連クラス(子ではない、is-aの関係ではありますが、関係があります。つまり、ケーキに小麦粉がある、ミルクがある、クリームがあるなど)のすべての情報を取得します。遅延ロードの場合は、最初に同じテーブルからの識別子と値のみを持ちます(ケーキの場合にボウルで最初に必要となる必要な材料)。他のテーブルからのすべての情報は、必要に応じて、または使用時にフェッチされます。


8

遅延読み込み?まあ、それは単に、子レコードがすぐにフェッチされるのではなく、アクセスしようとするとすぐに自動的にフェッチされることを意味します。


3

遅延設定は、親オブジェクトのロード中に子オブジェクトをロードするかどうかを決定します。この設定は、親クラスのそれぞれの休止状態マッピングファイルを実行する必要があります。Lazy= true(子をロードしないことを意味します)デフォルトでは、子オブジェクトの遅延ロードはtrueです。 。これにより、親でgetChild()メソッドを呼び出してアプリケーションで明示的に呼び出されない限り、子オブジェクトが読み込まれないようになります。この場合、親でgetChild()が実際に呼び出されたときにhibernateが新しいデータベース呼び出しを発行して子を読み込みますオブジェクトですが、親がロードされるときに子オブジェクトをロードする必要がある場合もあります。lazy = falseにすると、データベースから親がロードされるときにhibernateが子をロードします。Exampleslazy= true(デフォルト)UserクラスのAddressの子は、頻繁に必要とされない場合は遅延させることができます。


3

遅延読み込みを使用すると、関連付けの取得を延期したり、フェッチ戦略をより適切に制御したりできます。

EAGERロードを使用する場合は、クエリ時にオーバーライドできないグローバルフェッチプランを定義します。つまり、エンティティモデルの設計中に行った決定に制限されます。EAGERフェッチはコードのにおいですフェッチ戦略は、クエリ時ポリシーであり、それが別のビジネスユースケースと異なる場合がありますので、。

フェッチ戦略は、あまりにも多くのEAGERフェッチが深刻なパフォーマンス関連の問題を引き起こす可能性がありますように、非常に重要な側面です。


2

遅延読み込みは、オブジェクトの初期化を必要な時点まで延期するためにコンピュータープログラミングで一般的に使用される設計パターンです。適切に適切に使用すれば、プログラムの運用効率に貢献できます。

ウィキペディア

hibernate.orgからの遅延読み込みのリンク


1

まあそれは単に、現在使用しない大量のデータを一度にロードするのではなく、現在必要なデータをロードすることを意味します。これにより、アプリケーションの読み込み時間が通常よりも速くなります。


0

Hiberanteはエンティティとコレクションの両方の遅延初期化機能をサポートしています。Hibernateエンジンは、クエリ対象のオブジェクトのみをロードし、他のエンティティまたはコレクションはロードしません。

lazy = "false"の場合、デフォルトのロードでは、唯一の子の初期化に関する言及はlazyです。trueの場合、親がロードされている場合、子はサポートされません。


0

遅延設定は、親オブジェクトのロード中に子オブジェクトをロードするかどうかを決定します。この設定は、親クラスのそれぞれの休止状態マッピングファイルを実行する必要があります。Lazy= true(子をロードしないことを意味します)デフォルトでは、子オブジェクトの遅延ロードはtrueです。 。


0

驚いたことに、画面の背後にある休止状態によってそれがどのように達成されるかについての回答はありません。

遅延読み込みは、パフォーマンス上の理由から休止状態で効果的に使用される設計パターンです。これには、以下の手法が含まれます。


1.バイトコードインストルメンテーション

そのエンティティオブジェクトへのすべての呼び出しをインターセプトするhibernate フックを使用して基本クラス定義を拡張します。

コンパイル時または実行[ロード]時に実行されます

1.1 コンパイル時間

  • コンパイル後の操作

  • 主にmaven / antプラグインによる

1.2 実行時間

  • コンパイル時のインストルメンテーションが行われていない場合、これは実行時に作成されますjavassistのようなライブラリを使用します

2.プロキシ

Hibernateが返すエンティティオブジェクトは、実際のタイプのプロキシです。

参照: Javassist。主なアイデアは何ですか?実際にどこで使用しますか?

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.