1. 즉시 로딩 (EAGER Loading)
엔티티를 조회할 때 연관된 엔티티도 함께 조회한다.
@Entity
@Getter @Setter
public class Member {
@Id @GeneratedValue
@Column(name = "MEMBER_ID")
private Long id;
@Column(name = "USERNAME")
private String name;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "TEAM_ID")
private Team team;
}
- @ManyToOne (fetch = FetchType.EAGER) 지정함으로써 즉시 로딩 선언
//즉시 로딩
Member findMember = em.find(Member.class, member.getId());
Team team = findMember.getTeam(); //객체 그래프 탐색
- em.find(Member.class, member.getId())을 호출할 때 회원 엔티티와 연관된 팀 엔티티도 함께 조회한다.
- JPA 구현체는 즉시 로딩을 최적화하기 위해 가능하면 조인 쿼리를 사용한다.
위 예제를 실행해 보면 로딩 실행 SQL에서 JPA가 내부 조인(INNER JOIN)이 아닌 외부 조인(LEFT OUTER JOIN)을 사용하였다. (외부 조인보다 내부 조인이 성능과 최적화에서 더 유리하다)
(1) 외래 키에 NOT NULL 제약 조건을 설정하면 값이 있는 것을 보장한다 => 내부 조인 사용
@JoinColumn(nullable = false)
(2) @ManyToOne(fetch = FetchType.EAGER, optional = false)
2. 지연로딩 (LAZY Loading)
연관된 엔티티를 실제 사용할 때 조회한다.
@Entity
@Getter @Setter
public class Member extends BaseEntity{
@Id @GeneratedValue
@Column(name = "MEMBER_ID")
private Long id;
@Column(name = "USERNAME")
private String name;
@ManyToOne(fetch = FetchType.LAZY) //프록시객체로 조회한다.
@JoinColumn(name = "TEAM_ID")
private Team team;
}
- @ManyToOne(fetch = FetchType.LAZY) 으로 지연 로딩 선언
//지연로딩
Member findMember = em.find(Member.class, member.getId());
Team team = member.getTeam(); //프록시 객체
team.getName(); //프록시 초기화가 일어난다.
- em.find(Member.class, member.getId())를 호출하면 회원만 조회하고 팀은 조회하지 않는다.
3. 프록시와 즉시 로딩 주의
- 모든 연관관계에서 지연 로딩만 사용하자.
- 실무에서는 절대 즉시 로딩을 사용하지 마라!
- JPQL fetch 조인이나, 엔티티 그래프 기능을 사용해서 해결하자.
- 즉시 로딩을 적용하면 예상하지 못한 SQL이 발생한다.
- 즉시 로딩은 JPQL에서 N+1 문제를 일으킨다.
- @ManyToOne, @OneToOne은 default가 즉시 로딩이다. => 지연 로딩으로 바꿔주어야 한다.
- @OneToMany, @ManyToMany는 기본이 지연 로딩이다.
반응형
'JPA > JPA' 카테고리의 다른 글
[JPA] 값 타입 (0) | 2022.01.04 |
---|---|
[JPA] 영속성 전이(CASCADE)와 고아 객체 제거 (0) | 2022.01.03 |
[JPA] 프록시 (Proxy) (0) | 2022.01.03 |
[JPA] @MappedSuperclass (0) | 2022.01.03 |
[JPA] 상속 관계 매핑 (0) | 2022.01.03 |
댓글