API から、プロキシと関係があることがわかりました。session.get
しかし、プロキシに関する多くの情報を見つけることができず、呼び出しとの違いがわかりませんsession.load
。誰かが説明してくれたり、参照ページに案内してくれませんか?
ありがとうございました!!
API から、プロキシと関係があることがわかりました。session.get
しかし、プロキシに関する多くの情報を見つけることができず、呼び出しとの違いがわかりませんsession.load
。誰かが説明してくれたり、参照ページに案内してくれませんか?
ありがとうございました!!
これは本 Hibernate in Action からのものです。良い人はこれを読んで..
識別子によるオブジェクトの取得 次の Hibernate コード スニペットは、データベースから User オブジェクトを取得します。
User user = (User) session.get(User.class, userID);
get() メソッドは、識別子がクラスの 1 つのインスタンスを一意に識別するため、特別です。したがって、アプリケーションが識別子を永続オブジェクトへの便利なハンドルとして使用するのは一般的です。識別子による取得では、オブジェクトの取得時にキャッシュを使用できるため、オブジェクトが既にキャッシュされている場合にデータベース ヒットを回避できます。Hibernate は load() メソッドも提供します。
User user = (User) session.load(User.class, userID);
load() メソッドは古いです。ユーザーのリクエストにより、Hibernate の API に get() が追加されました。違いは些細なことです:
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 では、proxy は指定された識別子の値を持つオブジェクトであり、そのプロパティはまだ初期化されておらず、一時的な偽のオブジェクトのように見えます。行が見つからない場合、ObjectNotFoundException がスローされます。
session.get() は常にデータベースにヒットし、プロキシではなく、データベースの行を表すオブジェクトである実際のオブジェクトを返します。行が見つからない場合は、null を返します。
これらのメソッドでのパフォーマンスも diff になります。2つの間...
「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 のコミットが楽観的ロック例外で失敗することを望んでいますが、ここでは成功します。
"load" の代わりに "get" を使用すると、問題を回避できます。これは、get がすぐに選択を発行し、バージョン番号が楽観的ロック チェックのために正しいタイミングで読み込まれるためです。
load() がキャッシュまたはデータベースからオブジェクトを見つけることができず、例外がスローされ、load() メソッドが null を返すことはありません。
オブジェクトが見つからない場合、get() メソッドは null を返します。load() メソッドは、実際の永続インスタンスの代わりにプロキシを返す場合があります get() はプロキシを返しません。
また、オブジェクトが存在しない場合は例外がスローされるため、load を使用する際には注意が必要です。オブジェクトが存在することが確実な場合にのみ使用する必要があります。