[JPA] 8. エージェントとの関連付けの管理-エージェント


[JPA] 8. エージェントとの関連付けの管理


Java ORM標準JPAプログラミング学習記録

👀 プロキシとインスタントロード、遅延ロード


エージェントを使用すると、データベースで最初からクエリーするのではなく、実際に使用するときにデータベースで関連オブジェクトをクエリーできます.一般的なオブジェクトでは、結合を使用してクエリーを行うことが有効です.JPAは、즉시 로딩および지연 로딩で両方を同時にサポートしている.

📍 8.1プロキシサーバ


エンティティを問い合わせる場合、関連付けられたエンティティは常に使用できません.ビジネスロジックに基づいて関連するエンティティを使用する場合があり、そうでない場合があります.
JPAは、この問題を解決するために、エンティティが実際に使用されるまで지연 로딩と呼ばれるデータベースクエリを遅延させる方法を提供しています.
遅延ロードを使用する場合は、프록시 객체と呼ばれる実際のエンティティオブジェクトではなく、データベースクエリの偽オブジェクトを遅延させる必要があります.em.find() vs em.getReference()
  • em.find():エンティティを問合せます.永続性コンテキストにエンティティがない場合、クエリーDB
  • em.getReference():クエリーされていないDBを返し、実際のエンティティ・オブジェクトを委任してX.DBアクセスを作成するプロキシ・オブジェクト
  • 💭 エージェントフィーチャー

  • 実際のクラスを継承して作成
  • 外観は実際のカテゴリと同じ
  • 使用の観点から、実際のオブジェクトかエージェントオブジェクトかを区別せずに使用する
  • 実際のオブジェクトへの参照を保持
  • プロキシオブジェクトを呼び出すメソッド実オブジェクトを呼び出すメソッド
  • 💭 プロキシオブジェクトの初期化

    Member findMember = em.getReference(Member.class, m.getId());
    //System.out.println(findMember.getClass());
    //System.out.println(findMember.getId());
    System.out.println(findMember.getUserName());
  • findMember.getUserName()実際のデータをコールで問い合わせる
  • 実際のエンティティが作成されていない場合は、영속성 컨텍스트で初期化(エンティティの作成を要求)
  • 영속성 컨텍스트DBクエリに実際のエンティティを作成
  • 프록시 객체作成したエンティティ・オブジェクトの参照をMember targetメンバー変数
  • に保持
  • 프록시 객체実際のエンティティオブジェクトを呼び出すgetUserName()によって結果が返されます.
  • エージェントの特徴
  • 初回使用時に1回のみ初期化(2回はサポートされていません)

  • プロキシオブジェクトを初期化すると、プロキシオブジェクトは実際のエンティティになりません.エージェントオブジェクトが初期化されると、エージェントオブジェクトから実際のエンティティにアクセスできます.

  • プロキシオブジェクトは元のエンティティを継承するので、タイプをチェックするときは特に注意してください(=比較ではなくインスタンスofを使用します).
  • Member findMember1 = em.getReference(Member.class, m.getId());
    System.out.println(findMember1.getClass() == Member.class); //false
    System.out.println(findMember1 instanceof Member); //true
  • 永続性コンテキストでエンティティが見つかった場合は、DBを問い合わせる必要はありません.em.getReference()が呼び出されても、実際のエンティティ
  • が返されます.
    Member findMember1 = em.find(Member.class, m.getId());
    Member findMember2 = em.getReference(Member.class, m.getId());
    System.out.println(findMember1.getClass());
    System.out.println(findMember2.getClass());
    // 출력 => 둘다 엔티티 반환
    class com.jpa.db.Member
    class com.jpa.db.Member
  • 準永続状態でエージェントを初期化中に異常が発生しました(永続コンテキストを初期化できません)
  • em.detach(findMember1);
    System.out.println(findMember1.getUserName());
    //커넥션 에러
    org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl stop

    💭 プロキシ認証

    PersistenceUnitUtil().isLoaded():プロキシインスタンスを初期化するかどうかを確認
    Member refMember = em.getReference(Member.class, m.getId());
    //System.out.println(refMember.getClass());
    System.out.println(emf.getPersistenceUnitUtil().isLoaded(refMember));
    
    初期化されていない場合はfalseを返します.プロキシインスタンスが初期化されているか、または初期化されていない場合はtrueを返します.