2011-11-08 12 views
9

私は、Hibernate 3.6 session.get()session.load()の返されたオブジェクトと動作の違いを理解しようとしています。 javadocからHibernate 3.6 - session.get()vs session.load()

のget():

戻り 与えられた識別子、またはそのような永続的なインスタンスが存在しない場合はnullと指定されたエンティティクラスの永続インスタンス。

は、負荷()( インスタンスはすでにこのメソッドは、初期化されていないインスタンスを返すことはありませんその インスタンスを返し、セッションに関連付けられている場合。。):

リターンの永続的なインスタンスをインスタンスが存在すると仮定して、特定のエンティティクラスに という識別子を指定します。このメソッドは、 が非識別子メソッドにアクセスされたときにオンデマンドで初期化されるプロキシされたインスタンスを返します。

私は3つの質問があります

  1. load()プロキシを返す可能性がある場合javadocは言っていないが - 、事前にそれを知る方法はありますか?

  2. load()がプロキシを返すとき - つまり、load()はデータベースにアクセスしませんでしたが、正しいですか?次に、load()にデータベースに存在しない識別子を指定した場合はどうなりますか?セッション中に無効なIDを持つプロキシを持つようになりました(例外を取得せずに)。今、私は別の永続インスタンスがそのプロキシを指し示すようにしたい - それはうまくいくのだろうか?このシナリオでは、私はプロキシを初期化する必要はありません、私はそのIDが必要です(データベースにないので無効ですが、私は持っています)。だから私は私の記述が正しいかどうか尋ねていると思います。isInitialized()で返されたオブジェクトをload()の後にチェックアウトする必要があります。これは、有効なエンティティ(または少なくとも有効なプロキシ) ID。

  3. また、load()がプロキシを返すとどうなりますか。プロキシは既にセッションに関連付けられているインスタンスです。次に、get()の説明に従って: "インスタンスが既にセッションに関連付けられている場合は、そのインスタンスを返します。" - get()はプロキシを返しますか? get()の説明に従って: "このメソッドは決して初期化されていないインスタンスを返しません。

ありがとう!

UPDATE

は、次の正しいですか?

(A)load()get()は、まずDBに行く前にセッションキャッシュをチェックしようとします。そのため、常にDBにヒットしたり、常にプロキシを返すとは言えません。

(B)が初期化プロキシは、ここで読むことができるように、元のインスタンスと同じではありません。http://blog.xebia.com/2008/03/08/advanced-hibernate-proxy-pitfalls/

答えて

17

(1)、(3):

はい。あなたはそうです。load()get()は、最初に同じPKを持つインスタンスがセッションに残っているかどうかをチェックします。

「はい」の場合は、そのインスタンスをセッションから戻します。

いいえの場合、load()はプロキシを作成して返しますが、get()はプロキシまたは実際のエンティティクラスのインスタンスを返します。

両方のメソッドから返されるオブジェクトは、後でセッション内で関連付けられ、永続化されます。

get()またはload()戻り値のプロキシまたは実際のエンティティクラスは、get()またはload()を使用して現在のセッションで同じPKのインスタンスを初めて取得するかどうかによって異なります。

次のテストを実行することによって証明この動作をすることができます:それはプロキシである場合は、印刷されたクラス名は、実際のエンティティクラス名と同じ

Session session = HibernateUtil.getSessionFactory().openSession(); 

Item loadItem= (Item) session.load(Item.class, 1); 
System.out.println(loadItem.getClass().getName()); 

Item getItem = (Item) session.get(Item .class, 1); 
System.out.println(getItem .getClass().getName()); 

ではありません。効果を見るには、実行順序をload()get()に変更してください。

(2):

(ロードする場合は)プロキシを返し、それがload()選択図プロキシ中DBにアクセスしないPKに加えて、それらのマップされたプロパティがアクセスされ、インスタンスが存在していない場合にのみDBにアクセスします同じPK値を持つセッションがセッションに関連付けられます。

DBにアクセスすると、プロキシの同じPKを持つインスタンスがそのセッションに関連付けられます。プロキシから別のプロパティを再度取得するか、同じPKのインスタンスを取得するためにget()を使用すると、その値はセッションから検出されるため、DBはアクセスされません。例えば

/**Session starts***/ 
Item item = (Item) session.load(Item.class, new Long(1)); 
item.getId(); //Will not access DB as only the identifier property is access 
item.getDescription(); // access the DB and initialize the proxy . After that , the item proxy is said to be initialized 
item.getPrice(); //will not access DB as the item with the PK 1 can be get from the session 
Item item2 = session.get(Item.class, new Long(1)) //will not access DB as the item with the PK 1 can be get from the session 

あなたload()無効なIDを持つインスタンスと、その後は、プロパティにアクセスしたり、このプロキシに(例えばisInitialized()など)メソッドを呼び出すと、ObjectNotFoundExceptionがスローされます。したがって、ObjectNotFoundExceptionを捕まえることができれば、プロキシに無効なIDが読み込まれていることを意味します。

IDが実行時に有効であることを確認する場合は、get()を使用し、返されたインスタンスがnullであるかどうかを確認する必要があります。 load()は、外部キー制約を設定するときに便利です。 this

+0

1を参照してください。しかし、すでにセッションで初期化されたインスタンス(このID用)がある場合、プロキシではなくそのインスタンスが返されますか?また、javadocは「このメソッドはプロキシされたインスタンスを返すかもしれない」と言っています。「このメソッドは常にそうです」とは言いません。 2.これは設計上の欠陥のようなものです。プロキシを使用しているときに言うことによると、実際のIDをDBで表していることを確認したいからです。プロキシが他のインスタンスを指すようにする) - 私が使用するIDが初期化されるまで有効であることはわかりませんが、この場合はなぜプロキシを使用するのですか? – rapt

+0

3. 'load()'が初期化されたプロキシを返すか、初期化されたインスタンスだけを返した後に 'get()'を意味するのでしょうか?それが後であれば、同じID(プロキシとインスタンス)を保持する2つのオブジェクトがセッション内に存在するようになります。 BTW私はそれが同じDB IDを表す2つのプロキシを持つことが可能であることを知っています - ここで読むことができます:http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html_single/テキスト "第二に、プロキシを破ることは可能です。 - 私の元の質問のUPDATEの続きを見てください。 – rapt

+0

はい。あなたは正しいです。あなたの質問は、 'get()'と 'load()'に関する誤解を解消するのに役立ちます。私の更新をご覧ください –

関連する問題