본문으로 바로가기

즉시 로딩과 지연 로딩

category Spring/Spring JPA 2024. 3. 20. 21:14

지연 로딩 LAZY을 사용해서 프록시로 조회

 

 

Member.java

@Entity
@Table
@Getter
@Setter
public class Member extends BaseEntity{
    @Id @GeneratedValue
    @Column(name = "MEMBER_ID")
    private Long id;

    @Column(name = "USERNAME")
    private String username;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "TEAM_ID")
    private Team team;
}

 

예제

Main.java

// Team 생성 및 영속화
Team team = new Team();
team.setName("teamA");
em.persist(team);

// Member 생성 및 팀 연관 관계 설정 후 영속화
Member member1 = new Member();
member1.setUsername("member1");
member1.setTeam(team);
em.persist(member1);

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

Member m = em.find(Member.class, member1.getId()); // 프록시
System.out.println("m  = " + m.getTeam().getClass());

// 트랜잭션 커밋
tx.commit();
  • @ManyToOne(fetch = FetchType.LAZY) 어노테이션 설정하면, 프록시 타입으로 가져온다는 개념이다.
  • Member 만 딱 조회되고 Team 은 프록시로 조회된걸 알 수 있다.
  • m  = class hellojpa.Team$HibernateProxy$wIMSF5gC
Member m = em.find(Member.class, member1.getId()); // 프록시
            System.out.println("m  = " + m.getTeam().getClass());

            m.getTeam().getName(); // Team 조회 쿼리 실행 시점 , 초기화

 

즉시 로딩을 사용해서 함께 조회

 

예제

Member.java

@Entity
@Table
@Getter
@Setter
public class Member extends BaseEntity{
    @Id @GeneratedValue
    @Column(name = "MEMBER_ID")
    private Long id;

    @Column(name = "USERNAME")
    private String username;

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "TEAM_ID")
    private Team team;
}
  • 조회될때 같이 조회되는거 (쿼리 한번에 실행됨)

실행쿼리

 select
        member0_.MEMBER_ID as member_i1_3_0_,
        member0_.createdBy as createdb2_3_0_,
        member0_.createdDate as createdd3_3_0_,
        member0_.lastModifiedBy as lastmodi4_3_0_,
        member0_.lastModifiedDate as lastmodi5_3_0_,
        member0_.TEAM_ID as team_id7_3_0_,
        member0_.USERNAME as username6_3_0_,
        team1_.TEAM_ID as team_id1_7_1_,
        team1_.createdBy as createdb2_7_1_,
        team1_.createdDate as createdd3_7_1_,
        team1_.lastModifiedBy as lastmodi4_7_1_,
        team1_.lastModifiedDate as lastmodi5_7_1_,
        team1_.name as name6_7_1_ 
    from
        Member member0_ 
    left outer join
        Team team1_ 
            on member0_.TEAM_ID=team1_.TEAM_ID 
    where
        member0_.MEMBER_ID=?

 

 

프록시와 즉시로딩 주의

  • 가급적 지연 로딩만 사용(특히 실무에서)
  • 즉시 로딩을 적용하면 예상하지 못한 SQL 발생
  • 즉시 로딩은 JPQL에서 N + 1 문제를 일으킨다
  • @ManyToOne, @OneToOne은 기본이 즉시 로딩 => LAZY 로 설정
  • @OneToMany, @ManyToMany 는 기본이 지연로딩
  • 프록시 방법을 쓰면 죄다 조인되서 나중에 속도 엄청 느려져서 성능면에서 안좋음!!!!!

*N+1 문제 일으키는 것에 대한 해결? 방안은 뒤에서 다시 다룰거임, 근데 실무에서는 지연 로딩만 사용하는게 좋다!*

 

 

결론

  • JPQL fetch 조인이나, 엔티티 그래프 기능을 사용해라 (뒤에서 설명)
  • 즉시 로딩은 상상하지 못한 쿼리가 나간다.
  • 실무에서 즉시 로딩을 사용하지 마라

 

 

 

 

 

'Spring > Spring JPA' 카테고리의 다른 글

실습 5 - 연관관계 관리  (0) 2024.03.20
영속성 전이 : CASCADE와 고아 객체  (0) 2024.03.20
프록시  (0) 2024.03.20
실습 4 - 상속관계 매핑  (0) 2024.03.19
고급 매핑 - Mapped Supercalss  (0) 2024.03.19