JPA-遅延ロード、即時ロード


ロードポリシーは、JPAを使用する際に100%理解しなければならない部分です.

エージェントとの関連付けの管理


エンティティに関連関係がある場合、JPAはデフォルトの関連エンティティもクエリーしてインポートします.
しかし,我々が用いたエンティティが実際に関連付けられている場合,これは性能的に損失する.
JPAは、この問題を解決するためにプロキシ遅延ロードを使用することができます.

find() , getReference()


Entity Managerでは、エンティティを取得する方法を2つ用意しています.
em.find()とem.getReference()の使い方を理解します.
メソッド説明em.find()find()メソッドは、実際のエンティティをクエリーするために使用されます.Em.getReference()メソッドクエリは、データベースクエリの偽エンティティを遅らせる.
偽図元という言葉は実は理解しにくい.
もしいくつかの遅延ロードの概念があれば、実は難しくありませんが、私はこれらの概念が頭の中にないことを説明します.
たとえば、次の構造を持つメンバーというエンティティが存在します.
@Entity
@Getter
@Setter
public class Member {
    @Id @GeneratedValue
    @Column(name = "MEMBER_ID")
    private Long id;
    private String name;
}
次のクエリを行います.
Member member = new Member();
member.setName("member");

em.persist(member);
em.flush();
em.clear();

Member findMember = em.find(Member.class, member.getId());
System.out.println(findMember.getId());
System.out.println(findMember.getName());
新しいメンバーを保存してclearをリフレッシュした以上、メンバーを検索すると、永続性コンテキストはアプリケーションを起動するように完全に透明になります.メンバーをクエリーすると、永続的なコンテキストにデータが存在しないため、クエリーがデータベースに送信されます.em.find()を呼び出すとクエリーが実行され、エンティティが永続コンテキストに保存されます.
em.getReference()ではなくem.find()を使用するとどうなりますか?
getReferenceの説明を少し整理しましょう
彼は偽のエンティティを調べると言った.「ダミーエンティティ」
では、メンバーfindMember=em.getReference(メンバー.class,メンバー.getId()
コードを呼び出すと、データベース文にクエリーを送信せずにプロキシオブジェクトが返されます.
では、実際にデータが必要な場合はどうなりますか?
その時点で実際にデータをクエリーしてインポートします.
これが遅延ロードです.一番遅く使う時にロードする方法です.
これはどうすればいいですか?

プロキシサーバ


エージェントの概念が足りなければ、大丈夫です.
私から見れば、エージェントは非常に簡単で複雑なモデルの一つです.
つまり代理人と言える
私がしなければならないことを別のクラスに委任して、呼び出しの方法で代わりました.
getReferenceが呼び出されると、遅延ロードを許可するエージェントは、Targetというフィールドを持つライブラリ内でエージェントのオブジェクトを作成し、実際のオブジェクトの参照を格納します.
実は文字だけでは難しいところがあると思います.

では、例を挙げて順番を話しましょう.
  • クライアントはメンバーです.getName()を呼び出します.
  • の初期には、MemberProxyにはターゲットが実際に参照されたオブジェクトはありません.したがって、この場合、永続性コンテキストで初期化する必要があります.
  • 永続コンテキストは、データを取得するためにデータベースを問合せます.
  • 実際のエンティティを生成します.
  • で生成されたエンティティの実際の方法target.getName()を呼び出します.
  • 実際にエージェントオブジェクトがない情報を使用するために最終的にエージェントメソッドを呼び出すと、実際のデータベースクエリによって初期化されます.

    仮想エージェント機能

  • エージェントオブジェクトは、初回使用時に1回のみ
  • を初期化する.
  • エージェントオブジェクトを初期化する場合、エージェントオブジェクトは実際のエンティティにはなりません.初期化後、エージェントオブジェクトを介して実際のエンティティ
  • にアクセスできます.

  • プロキシオブジェクトは元のエンティティを継承するので、タイプをチェックするときに特に注意してください(=instance ofではなく比較に失敗しました)

  • 検索するエンティティが永続コンテキストにすでに存在する場合は、em.getReference()を呼び出しても実際のエンティティに戻ります(重要)

  • エージェントが半永久的な状態にある場合、永続的なコンテキストでヘルプを得ることができず、エージェントを初期化すると問題が発生します.
    (HyperNateはorg.hibernate.LazyInitializationException異常をトリガーします)
  • em.getReference()を呼び出し、em.findクエリをエージェントとして永続性に格納されているエンティティとして呼び出すと、エージェントエンティティが返されます.エージェントが永続コンテキストのヘルプで動作しているため、永続コンテキストのヘルプで動作できない場合は、エラーが発生します.

    遅延ロード、即時ロード


    JPAでは、遅延ロードとインスタントロードのポリシーを選択できます.
    JPAは、fetch=fetchTypeをfetch別名の値としている.LAZYに設定すると、遅延ロードがサポートされます.
    この場合、特定のエンティティに関連付けられたエンティティがエージェントとして使用されます.
    したがって、データを直接使用する場合は、データベースからデータをインポートする必要があります.
    ただし、JPAでは遅延ロードがサポートされていない場合があり、特定の条件を満たさない場合、1:1関係では遅延ロードは許可されません.
    詳細については、次のリンクを参照してください.
    https://medium.com/@yongkyu.jang/jpa-%EB%8F%84%EC%9E%85-onetoone-%EA%B4%80%EA%B3%84%EC%97%90%EC%84%9C%EC%9D%98-lazyloading-%EC%9D%B4%EC%8A%88-1-6d19edf5f4d3
    JPAとOneToOneの関係でLazy Loadingを開始する条件
  • は、空の1:1関係を許可しません.すなわち、参照オブジェクトはoptional=falseとして指定できる関係でなければならない.
  • の双方向関係ではなく、一方向1:1の関係であるべきです.
  • @PrimaryKey Joinは許可されていません.親エンティティと子エンティティの間のリンクバーは、PKの場合を意味します.
  • 実際の操作では、基本ポリシーとして、すべての関係に遅延ロードが使用されます.
    必要に応じてJPQLを使用してjoin fetchを使用して遅延ロードを行うことができますが、クエリー時にデータをインポートできます.
    @OneToOneと@ManyToOneのデフォルト値はhaveなので、lazyに変更して使用する必要があります.