어떠한 Member 테이블과 Team 테이블이 있는데
Member는 Team에 속하기 때문에 Member는 Team_ID를 가지고 있다.
만약 Member 객체를 불러올 때, 그 멤버가 속한 팀의 정보를 다 불러와야할까??
방식에 따라 다르겠지만
JPA에서는 연관관계 데이터를 불러오는 방법 두 가지 방법을 제공한다.
(1) 지연 로딩 (FetchType.LAZY)
Member.java
@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;
// 이하 생략
}
지연 로딩은 영속성 컨텍스트가 Member 를 불러올 때, 연관관계에 있는 Team을 진짜 Team Table 을 조회해서 가져오진 않고 프록시 객체로 가져오는 방법
다대일 설정(@ManyToOne) 에 fetch 전략을 FetchType.LAZY로 하면 지연로딩으로 설정되는데,
이렇게 설정한 후 Member 객체를 불러와서 Team 객체를 살펴보면 HibernateProxy 객체임을 알 수 있다.
실제로 Team 객체의 필드를 조회해올 때 그 때 Team 테이블에 SELECT 쿼리가 실행된다.
Member와 Team을 자주 사용한다면
(2) 즉시 로딩 (fetch = FetchType.EAGER)
Member.java
@Entity
public class Member {
@Id
@GeneratedValue
private Long id;
@Column(name = "USERNAME")
private String name;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "TEAM_ID")
private Team team;
// 이하 생략
}
즉시 로딩을 사용하는 것이 좋다.
즉시로딩은 Member 객체를 불러올 때 Team 객체를 프록시 객체로 불러오지 않고
Member 테이블을 조회 시 Team 테이블을 같이 조회해온다.
조인을 이용하여 함께 조회해온다.
그런데 즉시로딩 사용 시 주의사항이 있다.
(3) 프록시와 즉시로딩 주의
- 가급적 지연 로딩만 사용할 것(특히 실무에서)
- 즉시 로딩을 적용하면 예상하지 못한 SQL이 발생한다.
- 즉시 로딩은 JPQL에서 N+1 문제를 일으킨다. ( 원하지 않았던 데이터까지 끌고오는 경향)
- @ManyToOne, @OneToOne은 기본이 즉시로딩 → LAZY로 설정해줘야 함
- @OneToMany, @ManyToMany는 기본이 지연 로딩이다.
지연 로딩 활용 시
Member와 Team은 자주 함께 사용한다면 → 즉시 로딩
Member와 Order는 가끔 사용 → 지연 로딩
Order와 Product는 자주 함께 사용 → 즉시 로딩
- 모든 연관관계에 지연 로딩을 활용하는게 좋다
- 실무에서 즉시 로딩을 사용하지 않는 편이 좋다
- JPQL fetch 조인이나, 엔티티 그래프 기능을 사용하라
- 즉시 로딩은 개발자가 예상하지 못했던 쿼리들이 나갈 수 있다.
'자바 > JPA' 카테고리의 다른 글
[JPA/Java] 값 타입 1 (기본 값, 임베디드(복합 값) 타입) (0) | 2023.03.06 |
---|---|
[JPA/Java] 영속성 전이 : Cascade, 고아 객체 (0) | 2023.03.03 |
[JPA/Java] 프록시(Proxy) (0) | 2023.02.27 |
[JPA/Java] 고급 매핑 (상속관계 매핑<조인, 단일 테이블>, @MappedSuperclass) (0) | 2023.02.21 |
[JPA/JAVA] 다양한 연관관계 매핑 (N:1, 1:N, 1:1, N:M) (0) | 2023.02.20 |
댓글