JPAディレイロード(LAZY)即時ロード(EAGER)


遅延ロード(LAZY)



内部メカニズムは上図の通りです.
ロード時にLazyロードを有効にしたTeamエンティティがプロキシオブジェクトとしてインポートされます.
次に、実際のオブジェクトを使用するときに初期化します.データベースにクエリーがあります.
-getTeam()を使用してTeamをクエリーすると、エージェントオブジェクトがクエリーされます.
- getTeam().getXXX()を使用してチームフィールドにアクセスすると、クエリーが行われます.
ほとんどのビジネスロジックでメンバーとチームを同時に使用する場合?
  • LAZYロードを使用すると、SELECTクエリはそれぞれ2回行われます.
  • ネットに2回乗って検索した話なので損失です.
  • は、この時点でJPQLのfetch joinを介してクエリとしてインポートされ、書き込まれる.
  • 即時ロード(EAGER)


    fetchタイプはEAGERに設定すればよい.(デフォルトはEAGER,@ManyToOne,@OneToOne…@XXXXToOne)
    ほとんどのJPAインプリメンテーションは、SQLを同時にクエリーするためにできるだけ結合を使用したいと考えています.
    これにより、実際のクエリーでは、1回のクエリーがクエリーされます.
    実行結果から,Teamオブジェクトもエージェントオブジェクトではなく実オブジェクトである.

    エージェントと即時ロードの注意事項

  • トラフィックは、可能な限り遅延ロードのみを使用します.
  • をすぐにロードすると、予期せぬSQLが発生します.
  • @ManyToOneが5個すべてEAGERに設定されています
  • 鳥人が5人現れる.業務上、より多くのテーブルがあります.
  • 直ちにJPQLにロードしてN+1の問題を引き起こす

  • 多くの複雑なクエリーを実際の作業で解決するために、JPQLがよく使われています.

  • EAGERは、戻るときにクエリーを行ったはずです.だからメンバー全員を連れてきてメンバー関係のチームを連れてきて
    ex)メンバーは2名、チームは2名.それぞれ違うチームです.
  • Team team1 = new Team();
    team1.setName("teamA");
    em.persist(team1);
    ​
    Team team2 = new Team();
    team2.setName("teamB");
    em.persist(team2);
    ​
    Member member1 = new Member();
    member1.setUsername("memberA");
    em.persist(member1);
    member1.changeTeam(team1);
    ​
    Member member2 = new Member();
    member2.setUsername("memberB");
    em.persist(member2);
    member2.changeTeam(team2);
    ​
    em.flush();
    em.clear();
    ​
    List<Member> members = em
                    .createQuery("select m from Member m", Member.class)
      .getResultList();
    ​
    tx.commit();
    運転結果から見ると
    1.メンバーの問合せと取得
    2.メンバーの列を埋め尽くすために、チームを別々に出します.
    ここでN+1の問題が発生する
    ->クエリーが発行されます.これは、N個の追加クエリーがあることを意味します.
    Hibernate: 
        /* select
            m 
        from
            Member m */ select
                member0_.id as id1_4_,
                member0_.createdBy as createdB2_4_,
                member0_.createdDate as createdD3_4_,
                member0_.lastModifiedBy as lastModi4_4_,
                member0_.lastModifiedDate as lastModi5_4_,
                member0_.age as age6_4_,
                member0_.description as descript7_4_,
                member0_.locker_id as locker_10_4_,
                member0_.roleType as roleType8_4_,
                member0_.team_id as team_id11_4_,
                member0_.name as name9_4_ 
            from
                Member member0_
    Hibernate: 
        select
            team0_.id as id1_8_0_,
            team0_.createdBy as createdB2_8_0_,
            team0_.createdDate as createdD3_8_0_,
            team0_.lastModifiedBy as lastModi4_8_0_,
            team0_.lastModifiedDate as lastModi5_8_0_,
            team0_.name as name6_8_0_ 
        from
            Team team0_ 
        where
            team0_.id=?
    Hibernate: 
        select
            team0_.id as id1_8_0_,
            team0_.createdBy as createdB2_8_0_,
            team0_.createdDate as createdD3_8_0_,
            team0_.lastModifiedBy as lastModi4_8_0_,
            team0_.lastModifiedDate as lastModi5_8_0_,
            team0_.name as name6_8_0_ 
        from
            Team team0_ 
        where
            team0_.id=?

    n/a.結論

  • ビジネスでは、LAZYロードポリシーをできるだけ使用します.
  • 実務では、ほとんどのMEMBERがTEAMとともに使用されている場合は、JPQLのfetch joinでこの時点で1回のクエリで使用をインポートしてください.
  • @ManyToOneと@OneToOneのように、@XXXXToOneの基本は即時ロード(EAGER)です.
  • @OneToMany,@ManyToManyのデフォルトは遅延ロードです.