ABOUT ME

-

오늘 방문자
-
어제 방문자
-
전체
-
  • 지연로딩, 즉시로딩
    JPA 2021. 8. 22. 21:56

    Team과 Member의 관계가 1:N이고

    member를 조회 할 때 member만 사용하는대 Team까지  가져오면 비용적 손해다.

    그럴 경우 LAZY로딩을 이용해 proxy로 조회하는 방법을 쓰면된다.

     

    ex) @ManyToOne(fetch = FetchType.LAZY) // 지연로딩

     

    주의사항

    1.기본은 모두 LAZY로딩으로 잡아 놓고, 필요한 부분만 EAGER로딩으로 변경하는 것을 권장하고 있다.

    이유

      1-1 JPQL로 작성시 N+1 이슈발생.

      1-2 다른 팀원이 member만 조회하려고 findById를 날렸는대, team 쿼리까지나가면 당황. 

     

    2. 연관관계 별로 fetch 기본값이 다름.

    @ManyToOne -> EAGER

    @OneToOne -> EAGER

    @ManyToMany -> LAZY

    @OneToMany -> LAZY  

     

     

    @Entity
    @Setter @Getter
    @NoArgsConstructor(access = AccessLevel.PROTECTED)
    @ToString(of = {"id", "name"})
    public class Team {
    
        @Id @GeneratedValue
        @Column(name = "team_id")
        private long id;
    
        private String name ;
    
        @OneToMany(mappedBy = "team")
        List<Member> members = new ArrayList<>();
    
        public Team(String name) {
            this.name = name;
        }
    }
    package study.datajap.entity;
    
    import lombok.*;
    
    import javax.persistence.*;
    
    @Entity
    @Setter @Getter
    @NoArgsConstructor(access = AccessLevel.PROTECTED)
    @ToString(of = {"id", "username", "age"})
    public class Member extends  BaseEntity{
    
        @Id @GeneratedValue
        private long id;
    
        private String username;
    
        private int age;
    
        @ManyToOne(fetch = FetchType.LAZY) // 지연로딩
        @JoinColumn(name = "team_id")
        private Team team;
    
        public Member(String username) {
            this.username = username;
        }
    
        public Member(String username, int age, Team team) {
            this.username = username;
            this.age = age;
            if(team != null){
                changeTeam(team);
            }
        }
    
        public Member(String username, int age) {
            this.username = username;
            this.age = age;
        }
    
        public void changeTeam(Team team){
            this.team = team ;
            team.getMembers().add(this);
        }
    }
    @Test
    public void 지연로딩 () {
        Optional<Member> byId = memberRepository.findById(2L); // fetch = FetchType.EAGER OR LAZY
        // byId.get().getTeam() // 호출 시점에 Team 쿼리 날림
    }
    Hibernate: 
        select
                member0_.id as id1_1_,
                member0_.reg_date as reg_date2_1_,
                member0_.update_date as update_d3_1_,
                member0_.reg_user_id as reg_user4_1_,
                member0_.update_user_id as update_u5_1_,
                member0_.age as age6_1_,
                member0_.team_id as team_id8_1_,
                member0_.username as username7_1_ 
            from
                member member0_ 
            where
                member0_.username=?

     

    즉시로딩으로 변경할 경우 join된 쿼리가 날라가게 된다.

        @ManyToOne(fetch = FetchType.EAGER) // 즉시로딩
        @JoinColumn(name = "team_id")
        private Team team;
    
        public Member(String username) {
            this.username = username;
        }
    Hibernate: 
        select
            member0_.id as id1_1_0_,
            member0_.reg_date as reg_date2_1_0_,
            member0_.update_date as update_d3_1_0_,
            member0_.reg_user_id as reg_user4_1_0_,
            member0_.update_user_id as update_u5_1_0_,
            member0_.age as age6_1_0_,
            member0_.team_id as team_id8_1_0_,
            member0_.username as username7_1_0_,
            team1_.team_id as team_id1_2_1_,
            team1_.name as name2_2_1_ 
        from
            member member0_ 
        left outer join
            team team1_ 
                on member0_.team_id=team1_.team_id 
        where
            member0_.id=?

     

     

    그러면 모든 연관관계를 LAZY로딩으로 바꾸었다가, 특정한 곳에서 member,team을 동시에 조회 하는 경우가 생긴다면???

    -> JPQL의 패치 조인을 사용하거나 , @Entitygraph를 사용하면 된다!

    'JPA' 카테고리의 다른 글

    [QueryDSL] 데이터 존재 유무 체크로직 성능 테스트  (0) 2021.03.25

    댓글

Designed by Tistory.