[JPA]永続性コンテキスト(3)-エンティティクエリー
エンティティ登録後のエンティティクエリーを理解します.
登録編で少しは分かりましたが、もう一度思い返せば…
JPAを使用してテーブルにデータを保存する場合、persist()メソッドは呼び出し時にINSERT文をDBに直ちに送信しません.
エンティティ・オブジェクトを永続コンテキスト(正確には永続コンテキスト)のプライマリ・キャッシュに配置するだけです.
では、find()も似たような予測ができるのではないでしょうか.
そうだ.find()メソッドもDBから必要なデータを直接取得することはありません.
まず、メインキャッシュにクエリーするエンティティがあるかどうかを検索し、ない場合はDBを使用してSELECT文を送信してエンティティをクエリーします.もちろん、このプロセスではメインキャッシュにも格納されます.
次のコードを実行するとどうなるか、一緒に図を見て、結果を予測します.🤔
🎈 サンプルコード1
上図はem.persist()コードの実行後を示しています.この絵が読めないなら、全編をもう一度読んだほうがいいです.ここで特に指摘するのは、繰り返したが、エンティティがデータベースに格納されていないことです.
em.find()メソッドがこの状態で実行された場合?
上の図に示すように、JPAはまずメインキャッシュに欲しいデータがあるかどうかを検索します.サンプルコードは、以前IDとして使用されていた値を使用してクエリーされるため、メインキャッシュにはクエリーするエンティティが格納されます.したがって、データベースからデータをインポートする必要はなく、メインキャッシュからインポートするだけです.
🎉 ログ1
上記の例で少し変更した場合、データを保存してからコードを書き直し、find()メソッドでデータをクエリーするとどうなりますか?クエリーするデータはメインキャッシュにないのでfind()メソッドが実行される瞬間、すぐにDBにSELECTクエリーを発行してデータをクエリーします.
△これらの部分は自分で修正してテストしたほうがいいです.
前編で述べたように、このようなプライマリキャッシュの存在は、パフォーマンスに有利である.
プライマリ・キャッシュがない場合、INSERT->SELECTはSQLを2回順番に実行しますが、プライマリ・キャッシュのため、1回のSELECT文を減らして同じ結果を得ることができます.
そして「同一性保障」の特徴がある.
例えばMyBatisのようにSQL Mapperで開発するとします!
同じデータを検索するために同じメソッドが2回呼び出された場合、各メソッドが返すオブジェクト(VOまたはDTOの可能性があります)は同じオブジェクトですか?
正解はNOであり,メソッドが実行されるたびに内部にnewキーワードで新しいオブジェクトが作成され,クエリの結果値がオブジェクトのフィールドに格納されるため,実際には同じ値を持つオブジェクトと言えるが,オブジェクト自体が同じとは思えない.すなわち、メモリ空間でそれぞれの空間を占めている.もちろんこれらの価格は同じです.
しかし、JPAは上の図のようにオブジェクトの同一性を保証しています!
私はまだJPAの内功がこの一致性を保証するのに何のメリットと重要なのか説明できません.これはゆっくり勉強して、悟ったら説明します.
これにより、3番目の永続性コンテキストが終了します.4番目のトピックでは、エンティティの変更例を使用して、永続性コンテキストの残りの特徴である「変更検出」と「遅延ロード」を理解します.
登録編で少しは分かりましたが、もう一度思い返せば…
JPAを使用してテーブルにデータを保存する場合、persist()メソッドは呼び出し時にINSERT文をDBに直ちに送信しません.
エンティティ・オブジェクトを永続コンテキスト(正確には永続コンテキスト)のプライマリ・キャッシュに配置するだけです.
では、find()も似たような予測ができるのではないでしょうか.
そうだ.find()メソッドもDBから必要なデータを直接取得することはありません.
まず、メインキャッシュにクエリーするエンティティがあるかどうかを検索し、ない場合はDBを使用してSELECT文を送信してエンティティをクエリーします.もちろん、このプロセスではメインキャッシュにも格納されます.
次のコードを実行するとどうなるか、一緒に図を見て、結果を予測します.🤔
🎈 サンプルコード1
Member member = new Member();
member.setId("member1");
member.setUsername("회원1");
// 1차 캐시에 저장됨
em.persist(member);
// 1차 캐시에서 조회
Member findMember = em.find(Member.class, "member1");
System.out.println("=========== END ===========");
tx.commit();
上図はem.persist()コードの実行後を示しています.この絵が読めないなら、全編をもう一度読んだほうがいいです.ここで特に指摘するのは、繰り返したが、エンティティがデータベースに格納されていないことです.
em.find()メソッドがこの状態で実行された場合?
上の図に示すように、JPAはまずメインキャッシュに欲しいデータがあるかどうかを検索します.サンプルコードは、以前IDとして使用されていた値を使用してクエリーされるため、メインキャッシュにはクエリーするエンティティが格納されます.したがって、データベースからデータをインポートする必要はなく、メインキャッシュからインポートするだけです.
🎉 ログ1
=========== END ===========
Hibernate:
/* insert hellojpa.Member
*/ insert
into
Member
(name, id)
values
(?, ?)
結果を見ればもっとよく理解できる.commit()メソッドを実行するまでINSERTもSELECTも実行されません.メインキャッシュ内でのみデータを移動でき、最終的にはデータINSERTも最後に実行されたと判断できます.上記の例で少し変更した場合、データを保存してからコードを書き直し、find()メソッドでデータをクエリーするとどうなりますか?クエリーするデータはメインキャッシュにないのでfind()メソッドが実行される瞬間、すぐにDBにSELECTクエリーを発行してデータをクエリーします.
△これらの部分は自分で修正してテストしたほうがいいです.
永続コンテキストの利点
前編で述べたように、このようなプライマリキャッシュの存在は、パフォーマンスに有利である.
プライマリ・キャッシュがない場合、INSERT->SELECTはSQLを2回順番に実行しますが、プライマリ・キャッシュのため、1回のSELECT文を減らして同じ結果を得ることができます.
そして「同一性保障」の特徴がある.
例えばMyBatisのようにSQL Mapperで開発するとします!
同じデータを検索するために同じメソッドが2回呼び出された場合、各メソッドが返すオブジェクト(VOまたはDTOの可能性があります)は同じオブジェクトですか?
正解はNOであり,メソッドが実行されるたびに内部にnewキーワードで新しいオブジェクトが作成され,クエリの結果値がオブジェクトのフィールドに格納されるため,実際には同じ値を持つオブジェクトと言えるが,オブジェクト自体が同じとは思えない.すなわち、メモリ空間でそれぞれの空間を占めている.もちろんこれらの価格は同じです.
しかし、JPAは上の図のようにオブジェクトの同一性を保証しています!
私はまだJPAの内功がこの一致性を保証するのに何のメリットと重要なのか説明できません.これはゆっくり勉強して、悟ったら説明します.
これにより、3番目の永続性コンテキストが終了します.4番目のトピックでは、エンティティの変更例を使用して、永続性コンテキストの残りの特徴である「変更検出」と「遅延ロード」を理解します.
Reference
この問題について([JPA]永続性コンテキスト(3)-エンティティクエリー), 我々は、より多くの情報をここで見つけました https://velog.io/@jin0849/JPA-영속성-컨텍스트3-엔티티-조회テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol