(JPA)즉시 로딩과 지연 로딩
즉시 로딩과 지연 로딩
지연 로딩 LAZY
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Entity
public class Member {
@Id
@GeneratedValue
private Long id;
@Column(name = "USERNAME")
private String name;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "team_id")
private Team team;
...
}
- Team 객체는 Proxy로 가져오게 된다.
- 실제 team을 사용하는 시점에 초기화를 통해 실제 Entity를 가져오게 된다.
- 비즈니스 로직 상 멤버와 팀을 함께 조회하는 경우가 적을 경우 사용하면 좋다.
즉시 로딩 EAGEA
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Entity
public class Member {
@Id
@GeneratedValue
private Long id;
@Column(name = "USERNAME")
private String name;
@ManyToOne(fetch = FetchType.EAGEA)
@JoinColumn(name = "team_id")
private Team team;
...
}
- member와 team을 조인을 통해 함께 조회한다.
- 비즈니스 로직 상 member와 team을 함께 조회하는 경우가 많을 경우 사용하면 좋다.
프록시와 즉시 로딩 주의
- 가급적 지연 로딩만 사용하는 것이 좋다.(실무 경험 상)
- 즉시 로딩을 적용하면 예상하지 못한 SQL이 발생할 때가 있다.
- 수 많은 조인이 발생 할 수 있다.
- 즉시 로딩은 JPQL에서 N+1 문제를 일으킨다.
- @ManyToOne, @OneToOne은 기본이 즉시 로딩이다. -> LAZY로 변경
- @OneToMany, @ManyToMany는 기본이 지연 로딩이다.
N+1 해결 방법
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Team teamA = new Team();
team.setName("teamA");
em.persist(teamA);
Team teamB = new Team();
team.setName("teamB");
em.persist(teamB);
Member memberA = new Member();
memberA.setUsername("memberA");
memberA.setTeam(teamA);
em.persist(memberA);
Member memberB = new Member();
memberB.setUsername("memberB");
memberB.setTeam(teamB);
em.persist(memberB);
em.flush();
em.clear();
List<Member> members = em.createQuery("select m from Member m", Member.class).getResultList();
위 코드에서 즉시 로딩 인 경우 member를 가져올때 team을 가져오는 쿼리가 하나 더 발생하기 때문에 N+1 문제가 발생한다.
해결방법
지연 로딩으로 변경한 후 fetch join 을 사용
@EntityGraph 어노테이션 사용
batch_fetch_size 설정
REFERENCE
#JPA_즉시로딩 #JPA_지연로딩
This post is licensed under CC BY 4.0 by the author.