[JPA]エージェント(JPA基本編by金英漢)


プロキシサーバ


Em.find()は、DBまたは永続コンテキストでエンティティオブジェクトを検索して返します.これとは異なり、em.getReference()は、データベース・クエリーを遅らせるエージェント・エンティティ・オブジェクトを返します.(永続性コンテキストでキャッシュにオブジェクトが含まれている場合は、プロキシではなくリアルオブジェクトが返されます!)
プロキシオブジェクト
プロキシオブジェクトは、実際のクラスと同じ外観の偽オブジェクトです.実際のエンティティオブジェクトへの参照(targetと呼ばれる)を保存することもできます.しかし、最初はtargetにnullが含まれていたため、接続はありませんでした.
エージェントオブジェクトの動作をコードで理解しましょう.memberにはエージェントオブジェクトが含まれています.getName(1)が呼び出されると、プロキシオブジェクトは、関数が存在しないため、永続性コンテキストで初期化(2)を要求します.次に(3)永続性コンテキストはDBで実際のメンバーオブジェクトを検索し,実際のエンティティオブジェクトをエージェントオブジェクトに関連付ける.現在、エージェントオブジェクトは(5)memberです.getName()をターゲットにします.getName()を使用して処理できます.

注意事項
エージェント・オブジェクトを実際のエンティティ・オブジェクトに接続する初期化プロセスは1回のみ発生し、ターゲットに入ったエンティティにアクセスして関数を呼び出します.これは、初期化後、エージェントオブジェクト(実際のエンティティオブジェクトではなく)が実際のエンティティオブジェクトとしてアクセスできることを意味します.最後に、初期化プロセスは永続性コンテキストで行われるため、永続性エージェントオブジェクトが準永続性状態にある場合、初期化要求時にエラーが発生します.
// 프록시객체 : 실제 클래스와 겉모양이 같음
Member findMember = em.getReference(Member.class, member.getId()); // 쿼리 안나감 

System.out.println("findMember.getId = " + findMember.getId());

// 쓰일 때 쿼리날림 (초기화)
System.out.println("findMember.getUsername = " + findMember.getUsername());
           
// 초기화 되서 초기화 요청 안함
System.out.println("findMember.getUsername = " + findMember.getUsername());
ここでfindMembergetId()が初期化されないのは、em.getReference時のmemberのためです.エージェントオブジェクトは、id値をgetId()に渡されたように保存します.
したがって、クエリがgetUsernameで伝播され、初期化され、getUsernameが再び呼び出されると、実際のオブジェクトがターゲットに接続されているため、クエリは伝播しません.
最後はfindMembergetUsername()のように初期化できますが、次の強制初期化も実行できます.
org.hibernate.Hibernate.initialize(entity);