카테고리 없음

[ Spring-Boot ] JPA 지연로딩(LAZY) 과 즉시로딩(EAGER)

사과씨앗 2021. 5. 23. 16:15
728x90
반응형

안녕하세요 이번 글에서는 JPA에서의 지연 로딩과 즉시 로딩에 대해서 알아보겠습니다.

 

두 가지 Entity를 예시로 만들겠습니다.

 

Member 

@Entity
@Getter @Setter
public class Member{

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "member_id")
    private Long Id;
    private String username;
    private int age;

    @ManyToOne()  
    @JoinColumn(name = "team1_id")
    private Team team;

 

Team

@Entity
@Getter
@Setter
public class Team {

    @Id
    @GeneratedValue
    @Column(name = "team_id")
    private Long id;
    private String name;

    @OneToMany(mappedBy = "team")
    private List<Member> members = new ArrayList<>();

연관관계의 주인은 Member로 설정하고 다대일 , 일대다 양방향을 사용하겠습니다.

 

이 상태에서 Member를 조회해봅시다.

    @Test
    public void LoadingTest(){

       //테스트용 데이터를 입력합니다.
        Team teamA = new Team("teamA");
        Team teamB = new Team("teamB");
        Team teamC = new Team("teamC");
        em.persist(teamA);
        em.persist(teamB);
        em.persist(teamC);

        Member member = new Member("memberA");
        Member memberB = new Member("memberB");
        Member memberC = new Member("memberC");

        member.changeTeam(teamA); 
        memberB.changeTeam(teamB);
        memberC.changeTeam(teamC);

        em.persist(member);
        em.persist(memberB);
        em.persist(memberC);

        //초기화
        em.flush();
        em.clear();

        List<Member> members = em.createQuery("select m from Member m", Member.class).getResultList();

    }

위처럼 각각의 멤버와 팀을 생성한 뒤 멤버를 조회한 다음 쿼리를 확인해 봅시다.

 

 [ 즉시 로딩 ]

가독성이 좀... ㅎㅎ 

 

위에서부터 차근차근 보면 member를 조회하는 select 쿼리가 한번 실행됩니다.

그다음 각 member들이 가지고 있는 Team들을 조회하는 select 쿼리가 3번 실행되는 것을 확인할 수 있습니다.

이 처럼 즉시 로딩을 사용할 시 데이터가 많아진다면 필요하지 않은 쿼리들도 어마어마하게 많이 생성될 수 있습니다.

위 같은 이유로 되도록 즉시 로딩보다는 지연 로딩을 권장합니다.

그럼 지연 로딩을 사용해서 결과를 확인해 보겠습니다. 

 

 

Member의 @ManyToOne fetch 속성을 LAZY로 변강 하겠습니다. ( @OneToMany는 기본 속성이 LAZY )

@Entity
@Getter @Setter
public class Member{

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "member_id")
    private Long Id;
    private String username;
    private int age;

    @ManyToOne(fetch = LAZY)  
    @JoinColumn(name = "team1_id")
    private Team team;

 

다시 테스트 코드를 실행해 보면

 

Member를 조회하는 select 쿼리만 실행된 것을 확인할 수 있습니다.

이때 조회된 Member 객체에 들어있는 Team객체는 프락시 객체가 Team을 상속한 상태로 생성되며

Team을 조회하는 순간 select 쿼리가 실행됩니다.

 

 

테스트 코드의 조회된 Member에서 getter를 사용하여 Team을 호출하여 보면

  @Test
    public void LoadingTest(){

       //테스트용 데이터를 입력합니다.
        Team teamA = new Team("teamA");
        Team teamB = new Team("teamB");
        Team teamC = new Team("teamC");
        em.persist(teamA);
        em.persist(teamB);
        em.persist(teamC);

        Member member = new Member("memberA");
        Member memberB = new Member("memberB");
        Member memberC = new Member("memberC");

        member.changeTeam(teamA);
        memberB.changeTeam(teamB);
        memberC.changeTeam(teamC);

        em.persist(member);
        em.persist(memberB);
        em.persist(memberC);

        //초기화
        em.flush();
        em.clear();

        List<Member> members = em.createQuery("select m from Member m", Member.class).getResultList();

 		 for (Member findMember : members) {
            System.out.println(" ======================================================= " );
            System.out.println("findMember.Team = " + findMember.getTeam());
            System.out.println(" ======================================================= " );
            
        }
    }

 

각각 의 Member 객체에서 Team을 호출하는 순간 select 쿼리가 실행되는 것을 확인할 수 있습니다.

 

 

결론 

 

- JPA에서는 즉시 로딩 X, 지연 로딩을 주로 사용해라!

 

- 한 번에 전부 조회가 필요한 경우 즉시 로딩이 아닌 fetch조인 또는 엔 티틴 그래프를 사용

 

감사합니다 ^^  

 

참고 영상 : https://www.inflearn.com/course/ORM-JPA-Basic

 

자바 ORM 표준 JPA 프로그래밍 - 기본편 - 인프런 | 강의

JPA를 처음 접하거나, 실무에서 JPA를 사용하지만 기본 이론이 부족하신 분들이 JPA의 기본 이론을 탄탄하게 학습해서 초보자도 실무에서 자신있게 JPA를 사용할 수 있습니다., 본 강의는 자바 백엔

www.inflearn.com

 

728x90
반응형