APIから、プロキシと関係があることがわかりました。しかし、私は、プロキシ上で多くの情報を見つけることができなかったと呼び出しの違いを理解していないsession.get
としますsession.load
。誰かが私を説明したり、参照ページに案内したりできますか?
ありがとうございました!!
回答:
これは、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になります。2つの間に...
もう一つ余分なポイント::
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のコミットが楽観的ロック例外で失敗することを望んでいますが、ここでは成功します。
「load」の代わりに「get」を使用すると、問題が回避されます。これは、getがすぐにselectを発行し、楽観的ロックチェックの正しいタイミングでバージョン番号がロードされるためです。
優れた説明はhttp://www.mkyong.com/hibernate/different-between-session-get-and-session-load
session.load()にあります。
これは常に、データベースを打つ。
Hibernateでは、プロキシは指定された識別子の値を持つオブジェクトであり、そのプロパティはまだ初期化されていません。一時的な偽のオブジェクトのように見えます。
ID値がデータベースに存在しない場合でも、指定されたID値を持つプロキシオブジェクトを常に返します。ただし、データベースからプロパティを取得してプロキシを初期化しようとすると、selectステートメントでデータベースにヒットします。行が見つからない場合、ObjectNotFoundExceptionがスローされます。
session.get():
常にデータベースにヒットし(キャッシュに見つからない場合)、実際のオブジェクト(プロキシではなく、データベース行を表すオブジェクト)を返します。
行が見つからない場合は、nullを返します。