본문 바로가기

JPA

N+1 문제

728x90
반응형
SMALL

Member.java

public class Member {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    @JsonBackReference
    @ManyToOne
    @JoinColumn(name = "team_id")
    private Team team;
}

Team.java

public class Team {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String teamName;
    @JsonManagedReference
    @OneToMany(mappedBy = "team")
    private List<Member> members = new ArrayList<>();
}

서로 양방향 관계이다.

 

 

    @GetMapping("")
    public List<Member> select(){
        List<Member> members1 = memberRepository.findAll();
        for (Member member:members1){
            System.out.println("member = " + member.getTeam().getTeamName());
        }
        return members1;

Member 와 양방향관계인 Team의 데이터를 조회해오는 로직인데,

JPA 에서는 Member 를 찾는 쿼리와 Team 를 찾는 쿼리를 두번 날린다.

 

사실 mybatis 에서는 한번의 쿼리로 다 찾을수 있는데도 말이다.

쓸데없이 쿼리를 두번 날려 N+1 현상이 일어난다.

결과값을 보면

해결법

 

Fetch join 을 해준다.

Fetch join 을 해주게 되면, 미리 쿼리로 테이블을 조인해서 가져오기 때문에, LAZY, EAGER 두개의 전략에 해당되는 해결법이다.

@Query("select m from Member m join fetch m.team t")
    List<Member> findAll();

 

적용후

join 쿼리가 나가게 되며, 쿼리가 최초 한번 발생한다. 

 

단점

1. JPA가 제공하는 Pagable 기능에는 사용 불가

 

2. 1:N 관계가 2개인 엔티티를 패치 조인 사용 불가

 

 



단점에 대한 해결법은, 추후에 포스팅 하겠습니다.

 

 

 

 

 

 

728x90
반응형
LIST