Hibernateでの1対1、多対1、および1対多のデフォルトのフェッチタイプ


103

Hibernateマッピングのデフォルトのフェッチタイプは何ですか?

探索して知ったのは、

  • 1対1の場合、それは熱心です。
  • 1 対多の場合は怠惰です。

しかし、Eclipseでテストした後、それはすべての人に熱心でした。

JPAとHibernateのどちらを使用しているかによって異なりますか?


1
JPAトピックにまだ関与している場合-古い回答が現在のHibernateバージョンでは古くなっているため、質問を新しい回答で更新しました。
アレクサンダーリュール2017

回答:


193

JPAとHibernateのどちらを使用しているかによって異なります。

JPA 2.0仕様、デフォルトは次のとおりです。

OneToMany: LAZY
ManyToOne: EAGER
ManyToMany: LAZY
OneToOne: EAGER

そして休止状態では、すべてがレイジーです

更新:

Hibernateの最新バージョンは、上記のJPAのデフォルトに対応しています。


11
「そして休止状態では、すべてがレイジーです」どうやら最近のバージョンでは変更されています。以下のAlexanderRühlの回答を参照してください。
Dinei

1
HibernateはJPA実装の1つなので、Hibernateを使用すると、JPAを使用することになります:)
xenteros

これは人気のあるクエリです。@Ashish Agarwal回答の最後の行を更新してください。Hibernateでは、今のところLazyではありません。
Saurabh Tiwari

最新のHibernateの動作に関して投稿を更新しました。
M Anouti 2018

eagerがすべてのマッピングのデフォルトのフェッチタイプであると主張する更新がありました。これは、現在の5.xおよび新しい6.x Hibernateドキュメントの両方で11.3章で反論されているため、編集を元に戻しました。さらに、単一のオブジェクトをフェッチするときにおそらくデータベース全体を選択することになるため、自動熱意を持たないことは推奨されません。
AlexanderRühl19年

51

質問をした時点で答えが正しかったのはわかっていますが、(今の私のように)人々はまだ彼らのWildFly 10の動作がなぜ違うのか疑問に思っているので、現在のHibernate 5の更新を提供したいと思います.xバージョン:

休止状態5.2ユーザガイドには、章に記載されている11.2。フェッチ戦略の適用

Hibernateの推奨事項は、すべてのアソシエーションに静的に遅延をマークし、熱心さのために動的フェッチ戦略を使用することです。残念ながら、これはすべての1対1および多対1の関連付けをデフォルトで積極的にフェッチする必要があると定義しているJPA仕様と対立し ます。Hibernateは、JPAプロバイダーとして、そのデフォルトを尊重します。

そのため、Hibernateは、JPAについて前述したAshish Agarwalのように動作します。

OneToMany: LAZY
ManyToOne: EAGER
ManyToMany: LAZY
OneToOne: EAGER

JPA 2.1仕様を参照)


また、JPA実装の代わりにネイティブの休止状態を使用すると、同じように動作しますか?
jMounir 2017年

@jMounir:私はまだ試していませんが、HibernateはJPAで定義されているように動作すると述べているので、Hibernateをそれ自体で使用する場合にそれが異なる理由がわかりません。どちらの場合も、デフォルトの戦略を上書きできます。
AlexanderRühl2017年

15

質問に答えるために、HibernateはJPA標準の実装です。Hibernateには独自の動作の癖がありますが、Hibernateのドキュメントによると

デフォルトでは、Hibernateはコレクションには遅延選択フェッチを使用し、単一値の関連付けには遅延プロキシフェッチを使用します。これらのデフォルトは、ほとんどのアプリケーションのほとんどの関連付けに意味があります。

そのため、宣言した関係のタイプに関係なく、Hibernateは常に遅延フェッチ戦略を使用してオブジェクトをロードします。1対1または多対1の関係にある単一のオブジェクトに対してレイジープロキシ(初期化されていないがnullではない)と、アクセスしようとすると値でハイドレートされるnullコレクションを使用します。

Hibernateは、を指定しない限り、オブジェクトにアクセスしようとしたときに、これらのオブジェクトに値を入力することのみを試みることを理解しておく必要があります fetchType.EAGER


0

単一値の関連付け、つまり、1対1および
多対1の場合:- デフォルトのLazy = proxy
プロキシ遅延読み込み:-これは、関連付けられたエンティティのプロキシオブジェクトが読み込まれることを意味します。つまり、関連付けられたエンティティのプロキシオブジェクトには、2つのエンティティを接続するIDのみが読み込まれます。
例:AとBは多対1の関連付けを持つ2つのエンティティです。つまり、Bごとに複数のAが存在する可能性があります。AのすべてのオブジェクトにはBの参照が含まれます
。`

public class A{
    int aid;
    //some other A parameters;
    B b;
}
public class B{
    int bid;
     //some other B parameters;
}

`
リレーションAには列(援助、入札、...エンティティAの他の列)が含まれます。
リレーションBには列(入札、...エンティティBの他の列)が含まれます。

プロキシは、Aがフェッチされると、IDのみがBに対してフェッチされ、IDのみを含むBのプロキシオブジェクトに格納されます。Bのプロキシオブジェクトは、最小限のフィールドのみを持つBのサブクラスであるプロキシクラスのオブジェクトです。入札はすでにリレーションAの一部であるため、リレーションBから入札を取得するためにクエリを実行する必要はありません。エンティティBの他の属性は、入札以外のフィールドがアクセスされた場合にのみ遅延読み込みされます。

コレクションの場合、ie-Many-to-ManyおよびOne-to-Many:-
デフォルトLazy = true


フェッチ戦略(select、joinなど)がlazyをオーバーライドできることにも注意してください。つまり、lazy = 'true'およびfetch = 'join'の場合、AをフェッチするとBまたはBsもフェッチされます(コレクションの場合)。考えれば理由がわかります。
単一値の関連付けのデフォルトのフェッチは「結合」です。
コレクションのデフォルトのフェッチは「選択」です。最後の2行を確認してください。私はそれを論理的に推論しました。

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