[JPA]遅延ロードとインスタントロード(JPA基本編by金英漢)


遅延ロードとインスタントロード


遅延ロードとインスタントロードについては、以前によく知られていたエージェントの概念を思い出してみましょう.)
たとえば、チームとメンバーが1対以上の関連関係を持っている場合、メンバーのチームを表示するたびに表示しますか?これは、お客様のビジネスニーズに依存します.その必要がなければ、それは無駄でしょう.
この場合、遅延ロードが使用されます.実際には、チームに関する情報をメンバーで取得する必要がある前に、データベースはクエリーを遅らせます.🤗 (どこかでいろいろなコンセプトを聞いたことがありますが…)
したがって、メンバーをブラウズするときに、以下のようにエージェントオブジェクトをTeamオブジェクトに入れます.そしてgetTeamのように、実際にチームが必要な場合に初期化!

遅延ロードに設定するには、以下に示すようにfetchオプションを簡単にLAZYに設定します.
public class Member {

    @ManyToOne(fetch = FetchType.LAZY) // 다대일(member관점) + 프록시객체로 조회
    @JoinColumn(name= "TEAM_ID") // FK는 뭔지
    private Team team;
    
    }
もちろん、逆に(すぐにロードする必要がある場合:常にメンバーとチームを同時に表示する)、fetchオプションをEAGERに設定できます.
 @ManyToOne(fetch = FetchType.EAGER) 
実際のコードを見て、クエリーがどのように行われているかを見てみましょう.
Member member = new Member();
member.setUsername("a");

Team team = new Team();
team.setName("b");
member.setTeam(team);

em.persist(member);
em.persist(team);

em.flush();
em.clear();


Member findMember = em.find(Member.class, member.getId());
System.out.println("member = " + findMember.getClass()); // 멤버객체
System.out.println("team = " + findMember.getTeam().getClass()); // 프록시객체
System.out.println("team = " + findMember.getTeam().getName()); // 초기화하면서 select문날림

即時ロード(EAGER)


JPAは最適化されるので、joinを使用してチームをインポートします.
 select
        .....
 from
     Member member0_ 
 left outer join
     Team team2_ 
         on member0_.TEAM_ID=team2_.TEAM_ID 
 where
     member0_.MEMBER_ID=?

遅延ロード(LAZY)


遅延ロード時にjoinは行わないことに注意してください.
select
        .....
from
   Member member0_ 
where
   member0_.MEMBER_ID=?
もちろん、JPAの最適化によって大きな違いがあるかもしれませんが、JPQLを使うともっと違いがあります.
JPQL
JQCLのメンバーを使用するには、クエリー全体でメンバーをクエリーします.
 Member member = new Member();
 member.setUsername("a");


Team team = new Team();
team.setName("b");
member.setTeam(team);



em.persist(member);
em.persist(team);



em.flush();
em.clear();
            
List<Member> members = em.createQuery("select m from Member m", Member.class).getResultList();
System.out.println(members);      
            

即時ロード(EAGER)


JPQLは、渡されたクエリーに従って作成されるため、JPAは最適化されません.したがって、メンバーにselect文が1回送信され、メンバーチームの値(クエリー全体に使用)が取得されます.select文は1回、合計2回、すぐにロードされます.
今はメンバーが少ないけど...メンバーが多く、他のチームに属している場合は、N+1の問題が発生する可能性があります.N+1問題は、メンバーの完全なクエリー時に発行されたクエリー(select*fromメンバーm)による他のNクエリー(各メンバーのチームにselect文がある)である.
Hibernate: 
 	select
        	....
 	from
        	Member member0_
       
Hibernate: 
    select
        team0_.TEAM_ID as team_id1_7_0_,
        team0_.name as name2_7_0_ 
    from
        Team team0_ 
    where
        team0_.TEAM_ID=?

遅延ロード(LAZY)


遅延ロードの場合、クエリーは1回のみ実行されます.
Hibernate: 
 	select
        	  ....
	 from
                  Member member0_
🔥n/a.結論🔥
できるだけすべての関連関係の遅延ロードをdefaultに設定し、本当に必要なときにすぐにロードに変更します.