私の知る限り、Hibernate の最初のレベルのキャッシュはセッション レベルのキャッシュを意味します。同じセッションで同じオブジェクトを複数回取得すると、キャッシュから取得されます。
半分正解です。あなたが言ったこととは別に、一次キャッシュの主な理由の 1 つは、同じセッションの下で、Hibernate が同じエンティティ (同じ ID を持つエンティティ) が同じオブジェクト インスタンスによって表されることを保証することです。
あなたが言ったことは、セッションからIDでエンティティを取得している場合にのみ正しいです:
Foo foo1 = session.get(Foo.class, 1L);
Foo foo2 = session.get(Foo.class, 1L);
の最初の呼び出しはget()
DB に移動して をロードしますFoo
。2 番目の呼び出しが呼び出されると、Hibernate はこのセッション内Foo
で ID 1 を持つものが既に取得されているかどうかを確認します。以前に取得されたので、Hibernate は単純にそのFoo
インスタンスを取得して返します。
ただし、このシナリオは、第 1 レベルのキャッシュが有効になる最も一般的な状況ではありません。このことを考慮:
// psuedo code only
User user = findByUserName("ADRIAN"); // assume ID = 777
List<User> users = findAllActiveUsers();
(上記のファインダーが Hibernate セッションを介して内部的にクエリを実行していると仮定します) Hibernate が 2 番目のクエリを実行すると、内部で Hibernate が SQL を実行し、結果セットを取得し、各レコードをユーザーに変換します。アクティブなユーザーの 1 人が ID 777 を持っていると仮定します。Hibernate がそのユーザー オブジェクト インスタンスを構築するとき、最初にそれが第 1 レベルのキャッシュに存在するかどうかをチェックします。以前に (ユーザー名で検索する前のクエリで) 取得されたため、新しい User オブジェクト インスタンスを構築する代わりに、Hibernate は以前に構築した (そして第 1 レベルのキャッシュに保存した) インスタンスを単純に再利用し、結果リストで使用します。
そうすることで、Hibernate は、同じセッション内で、異なる方法で同じエンティティ (同じ ID を持つ同じクラス) を取得した場合、エンティティが同じオブジェクト インスタンスであると常に想定できます。
Order
システムから sを取得しようとしている、より複雑な例を考えてみてくださいUser
。あなたが発見することは、それが(DBで)Order
同じを参照するときはいつでも、User
実際には同じUser
オブジェクトインスタンスを参照しているということです。
の質問に対して
閉じるまでセッションでどのように使用できるか
これは、Hibernate の内部実装の詳細です。ただし、概念的には、各セッションは内部的にマップを持ち、キーはエンティティ タイプ + ID、値はエンティティ オブジェクト インスタンスであると想像できます。
DB からクエリを実行し、セッションがエンティティを構築するときに、エンティティごとに、マップが既に存在する場合はマップから検索します。そうでない場合、セッションはエンティティを構築し、マップに配置します。すでに存在する場合、セッションは単にマップ内のエンティティを利用します
IDでエンティティを取得するときの同様のアイデア(スルーSession.get()
などSession.load()
)