JPA
N+1 문제
초록색거북이
2023. 3. 16. 16:41
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