JPA - 지연로딩과 즉시로딩

2023. 12. 10. 18:16·Spring/JPA
728x90
반응형
SMALL

 

즉시 로딩과 지연 로딩

  • 이전 포스트에서 프록시에 대해 배웠다.
  • 해당 객체와 연관된 다른 객체를 어떤 시점에 불러올지 , 어떤 타입으로 형성되는지 알아봤다.
  • JPA는 이런 프록시 기술을 사용해서 지연로딩을 사용한다.

객체 생성 코드

@Entity
@Data
@NoArgsConstructor(access = AccessLevel.PROTECTED)//기본생성자 protected
@ToString(of = {"id","username","age"})
public class Member extends BaseEntity {

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


    private String username;
    private int age;

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

    public Member(String username, int age, Team team) {
        this.username = username;
        this.age = age;
        if (team != null) {
            changeTeam(team);
        }
    }

    public Member(String teamA) {
        this.username = teamA;
    }

    private void changeTeam(Team team) {
        this.team = team;
        team.getMembers().add(this);
    }

    public Member(String username, int age) {
        this.username = username;
        this.age = age;
    }

}

 

Member와 Team객체 조회해보기

@Test
    @Transactional
    public void testLazyLoading(){
        Team team = new Team();
        team.setName("teamA");
        em.persist(team);

        Member member = new Member("memberA");
        em.persist(member);

        member.changeTeam(team);

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

        Member findMember = em.find(Member.class, member.getId());

        System.out.println("findMember = " + findMember.getClass());
        System.out.println("findMember.getTeam = " + findMember.getTeam().getClass());
        System.out.println("findMember.getTeam Proxy 초기화 = " + findMember.getTeam().getName());
    }

 

DDL 및 출력 결과

  • 실제로 Team의 필드값을 호출하기 전까지는 Proxy객체로 남아있다.
  • 필드값을 호출한 시점에는 select구문이 나가며 Proxy객체가 초기화된다. [지연로딩]
select
        member0_.member_id as member_id1_2_0_,
        member0_.created_by as created_by2_2_0_,
        member0_.created_date as created_date3_2_0_,
        member0_.last_modifed_by as last_modifed_by4_2_0_,
        member0_.last_modifed_date as last_modifed_date5_2_0_,
        member0_.age as age6_2_0_,
        member0_.team_id as team_id8_2_0_,
        member0_.username as username7_2_0_ 
    from
        member member0_ 
    where
        member0_.member_id=?

//System.out.println("findMember = " + findMember.getClass()) 결과
findMember = class study.jpa.queryDSL.domain.Member

//System.out.println("findMember.getTeam = " + findMember.getTeam().getClass()) 결과
findMember.getTeam = class study.jpa.queryDSL.domain.Team$HibernateProxy$2lVm0R3o

select
        team0_.team_id as team_id1_3_0_,
        team0_.created_by as created_by2_3_0_,
        team0_.created_date as created_date3_3_0_,
        team0_.last_modifed_by as last_modifed_by4_3_0_,
        team0_.last_modifed_date as last_modifed_date5_3_0_,
        team0_.name as name6_3_0_ 
    from
        team team0_ 
    where
        team0_.team_id=?

//System.out.println("findMember.getTeam Proxy 초기화 = " + findMember.getTeam().getName()) 결과
findMember.getTeam Proxy 초기화 = teamA

 

지연 로딩(Lazy Loading)

  • 로딩되는 시점에 Lazy로딩 설정이 되어 있는 Team엔티티는 프록시 객체로 가져온다.
  • 실제 객체를 사용하는 시점에 초기화가 되며, DB에 쿼리가 나간다.

 

즉시 로딩(Eager Loading)

  • 대부분의 JPA구현체는 조인을 사용해서 한번에 함꼐 조인하려고 한다.
  • 즉시 로딩시에는 하나의 쿼리에 연관관계를 모두 조인해서 가져온다.
  • getTeam을 통해 가져온 객체도 프록시객체가 아닌 실제 엔티티객체다.

 

 

프록시와 즉시 로딩시 주의 점

  • 실무에서는 모두 지연로딩을 사용한다.
  • 즉시 로딩시에는 모든 연관관계를 불러오는데 예상하지 못한 구문이 나올 수 있다. (모든 연관관계를 가져오기 때문)
  • 즉시 로딩은 JPQL에서 N+1문제를 일으킨다.(하나의 쿼리로 N개의 추가 쿼리가 나감)
  • 지연로딩을 사용하되 쿼리가 추가적으로 나가지 않게 하는 방법이있다.
  • JPQL의 fetch join을 사용한다.
  • 엔티티 그래프와 어노테이션, 배치 사이즈 설정으로 해결하는 방법도 있다.
  • XXXToOne어노테이션들은 기본이 즉시 로딩이므로 꼭 Lazy로 명시하여 사용하자.
  • OneToMany, ManyToMany는 기본이 지연로딩이다.

 

 

728x90
반응형
SMALL

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

@Where Deprecated되고 새로 쓰이는 @SQLRestriction  (1) 2024.11.20
JPA - DB 연결 예외 : 'url' attribute is not specified and no embedded datasource could be configured.  (0) 2024.06.14
JPA - Proxy  (2) 2023.12.10
JPA - MappedSuperClass  (1) 2023.12.10
JPA - 상속관계매핑  (0) 2023.12.09
'Spring/JPA' 카테고리의 다른 글
  • @Where Deprecated되고 새로 쓰이는 @SQLRestriction
  • JPA - DB 연결 예외 : 'url' attribute is not specified and no embedded datasource could be configured.
  • JPA - Proxy
  • JPA - MappedSuperClass
공부하고 기억하는 공간
공부하고 기억하는 공간
IT 비전공자로 시작하여 훌륭한 개발자가 되기 위해 공부하고 있는 공간입니다. 틀린 내용이나 부족한 부분이 있으면 댓글로 알려주세요 바로 수정하겠습니다.
    250x250
  • 공부하고 기억하는 공간
    IT - railroad
    공부하고 기억하는 공간
  • 전체
    오늘
    어제
    • 분류 전체보기 (325)
      • 면접 준비 (22)
        • OS (6)
        • Spring Security (0)
        • Java (3)
        • DB (11)
        • Network (3)
      • ElasticSearch (2)
      • Kafka (4)
      • Spring (22)
        • Spring Cloud (7)
        • Security6 (5)
        • JPA (12)
        • 프로젝트 리팩토링 회고록 (4)
        • Logging (8)
        • Batch (2)
      • Redis (17)
        • Redis 개념 (8)
        • Redis 채팅 (5)
        • Redis 읽기쓰기 전략 (1)
      • AWS (11)
      • 리눅스 (29)
        • 리눅스 마스터 2급 (5)
        • 네트워크(기초) (7)
        • 리눅스의 이해 (6)
        • 리눅스의 설치 (2)
        • 리눅스 운영 및 관리 (6)
      • JAVA-기초 (16)
        • JAVA기본 (11)
        • Design Pattern (5)
      • JSP (27)
        • JSP 기본 개념 (10)
        • JSP (1)
      • SQL (1)
      • TIL (36)
      • 문제 풀이 (2)
        • Programmers (9)
        • 백준 문제풀이 (28)
      • JavaScript (10)
      • HTML (17)
      • Ngrinder (1)
        • Ngrinder 문서 정리 (1)
  • 블로그 메뉴

    • 링크

    • 공지사항

    • 인기 글

    • 태그

      JS
      백준
      springsecurity
      자바
      redis
      리눅스
      자바 반복문
      프로그래머스
      Spring
      자바 알고리즘
      redis 채팅
      JavaScript
      HTML
      레디스
      자바기초
      Springframework
      자바 면접질문
      java
      리눅스마스터2급정리
      스프링프레임워크
      Spring Data Redis
      자바스크립트
      자바 면접
      jsp기초
      spring redis
      CSS
      Til
      JSP
      jsp request
      리눅스마스터2급
    • 최근 댓글

    • 최근 글

    • hELLO· Designed By정상우.v4.10.3
    공부하고 기억하는 공간
    JPA - 지연로딩과 즉시로딩
    상단으로

    티스토리툴바