APIから、プロキシと関係があることがわかりました。しかし、プロキシに関する多くの情報を見つけることができず、session.get
とsession.load
の呼び出しの違いを理解できません。誰かが私を説明するか、リファレンスページに案内してくれますか?
ありがとうございました!!
Hibernateフォーラム から:
これはHibernate in Actionの本から。良い人はこれを読んで..
識別子によるオブジェクトの取得次のHibernateコードスニペットは、データベースからUserオブジェクトを取得します。
User user = (User) session.get(User.class, userID);
Get()メソッドは、識別子がクラスの単一のインスタンスを一意に識別するため、特別です。そのため、アプリケーションでは、永続オブジェクトへの便利なハンドルとして識別子を使用するのが一般的です。識別子による検索では、オブジェクトを取得するときにキャッシュを使用できるため、オブジェクトが既にキャッシュされている場合にデータベースヒットを回避できます。 Hibernateはload()メソッドも提供します:
User user = (User) session.load(User.class, userID);
Load()メソッドは古いです。 get()は、ユーザーのリクエストによりHibernateのAPIに追加されました。違いは簡単です。
Load()がキャッシュまたはデータベースでオブジェクトを見つけることができない場合、例外がスローされます。 load()メソッドは決してnullを返しません。オブジェクトが見つからない場合、get()メソッドはnullを返します。
Load()メソッドは、実際の永続インスタンスの代わりにプロキシを返す場合があります。プロキシは、実際のオブジェクトに初めてアクセスしたときに実際のオブジェクトの読み込みをトリガーするプレースホルダーです。一方、get()は決してプロキシを返しません。 get()とload()の選択は簡単です。永続オブジェクトが存在し、存在しないことを例外と見なすことが確実な場合、load()が適切なオプションです。指定された識別子を持つ永続インスタンスがあるかどうかわからない場合は、get()を使用して戻り値をテストし、nullかどうかを確認します。 load()を使用するとさらに意味があります。アプリケーションは、データベースにアクセスして永続状態を取得することなく、永続インスタンスへの有効な参照(プロキシ)を取得できます。したがって、load()は、キャッシュまたはデータベースに永続オブジェクトが見つからない場合に例外をスローしない場合があります。後でプロキシにアクセスすると、例外がスローされます。もちろん、識別子によるオブジェクトの取得は、任意のクエリを使用するほど柔軟ではありません。
まあ、少なくともnhibernateでは、session.Get(id)はデータベースからオブジェクトをロードしますが、session.Load(id)はサーバーから離れずにプロキシオブジェクトのみを作成します。 POCO(またはPOJO :)の他のすべての遅延読み込みプロパティと同様に機能します。その後、このプロキシをオブジェクト自体への参照として使用して、関係などを作成できます。
Idのみを保持し、必要に応じて残りをロードするオブジェクトを持つようなものだと考えてください。リレーションシップ(FKなど)を作成するためにそれを渡すだけの場合は、IDが必要です。
session.load()は、データベースにアクセスすることなく、常に「プロキシ」(Hibernate用語)を返します。 Hibernateでは、プロキシは特定の識別子値を持つオブジェクトであり、そのプロパティはまだ初期化されていません。一時的な偽オブジェクトのように見えます。行が見つからない場合、ObjectNotFoundExceptionがスローされます。
session.get()は常にデータベースにアクセスし、プロキシではなくデータベース行を表すオブジェクトである実際のオブジェクトを返します。行が見つからない場合、nullを返します。
これらのメソッドのパフォーマンスもdiffになります。二人の間.
もう1つの追加ポイント::
hibernate Sessionクラスのgetメソッドは、オブジェクトがキャッシュとデータベースの両方で見つからない場合、nullを返します。一方、オブジェクトがキャッシュ上およびデータベース上で見つからず、nullを返さない場合、load()メソッドはObjectNotFoundExceptionをスローします。
「get」の代わりに「load」を使用する間接的な結果の1つは、バージョン属性を使用した楽観的ロックが期待どおりに機能しない可能性があることです。ロードが単にプロキシを作成し、データベースから読み取らない場合、バージョンプロパティはロードされません。バージョンは、後でオブジェクトのプロパティを参照して選択をトリガーした場合にのみロードされます。それまでの間、別のセッションでオブジェクトを更新できます。セッションには、楽観的ロックチェックを行うために必要な元のバージョンがありません。したがって、セッションの更新は、警告なしで他のセッションの更新を上書きします。
同じ識別子を持つオブジェクトを使用する2つのセッションでこのシナリオをスケッチしようとしています。 DBのオブジェクトの初期バージョンは10です。
Session 1 Session 2
--------- ---------
Load object
Wait a while..
Load object
Modify object property
[triggers db 'select' -
version read as 10]
Commit
[triggers db update,
version modified to 11]
Modify object property
[triggers db 'select' -
version read as 11]
Commit
[triggers db update,
version modified to 12]
セッション1のコミットが楽観的なロック例外で失敗するようにしたいのですが、ここでは成功します。
Getはすぐにselectを発行し、楽観的ロックチェックの正しい時間にバージョン番号がロードされるため、「load」の代わりに「get」を使用すると問題が回避されます。
また、オブジェクトが存在しない場合は例外をスローするため、loadの使用時には注意する必要があります。オブジェクトが存在することが確実な場合にのみ使用する必要があります。
load()はキャッシュまたはデータベースからオブジェクトを見つけることができず、例外がスローされ、load()メソッドは決してnullを返しません。
オブジェクトが見つからない場合、get()メソッドはnullを返します。 load()メソッドは、実際の永続インスタンスの代わりにプロキシを返す場合があります。get()はプロキシを決して返しません。
優れた説明は http://www.mkyong.com/hibernate/different-between-session-get-and-session-load にあります
session.load():
データベースにヒットすることなく、常に「プロキシ」(休止状態用語)を返します。
Hibernateでは、プロキシは指定された識別子の値を持つオブジェクトであり、そのプロパティはまだ初期化されていません。一時的な偽オブジェクトのように見えます。
ID値がデータベースに存在しない場合でも、指定されたID値を持つプロキシオブジェクトを常に返します。ただし、データベースからプロパティを取得してプロキシを初期化しようとすると、selectステートメントでデータベースにヒットします。行が見つからない場合、ObjectNotFoundExceptionがスローされます。
session.get():
。
行が見つからなかった場合、nullを返します。