JPA에서는 데이터를 조회할 때 즉시 로딩(EAGER)과 지연 로딩(LAZY) 두 가지 방식이 있다. 이 두 가지 방식을 간단하게 설명하면 즉시 로딩은 데이터를 조회할 때 연관된 데이터까지 한 번에 불러오는 것이고, 지연 로딩은 필요한 시점에 연관된 데이터를 불러오는 것이라고할 수 있다.
FetchType이란, JPA가 하나의 Entity를 조회할 때, 연관관계에 있는 객체들을 어떻게 가져올 것이냐를 나타내는 설정값이다.
JPA는 ORM 기술로, 사용자가 직접 쿼리를 생성하지 않고, JPA에서 JPQL을 이용하여 쿼리문을 생성하기 때문에 객체와 필드를 보고 쿼리를 생성한다.
따라서, 다른 객체와 연관관계 매핑이 되어있으면 그 객체들까지 조회하게 되는데, 이때 이 객체를 어떻게 불러올 것인가를 설정할 수 있다.
fetch의 디폴트 값을 @xxToOne에서는 EAGER, @xxToMany에서는 LAZY이다.
즉시로딩이란 데이터를 조회할 때, 연관된 모든 객체의 데이터까지 한 번에 불러오는 것이다.
@Entity
public class Member {
@Id @GeneratedValue
private Long id;
private String username;
@ManyToOne(fetch = FetchType.EAGER) //Team을 조회할 때 즉시로딩을 사용하곘다!
@JoinColumn(name = "team_id")
Team team;
}
@Entity
public class Team {
@Id @GeneratedValue
private Long id;
private String teamname;
}
JPQL로 Member 1건 조회
Member findMember = em.createQuery("select m from Member m", Member.class).getSingleResult();
실제 SQL 코드
//멤버를 조회하는 쿼리
select
member0_.id as id1_0_,
member0_.team_id as team_id3_0_,
member0_.username as username2_0_
from
Member member0_
//팀을 조회하는 쿼리
select
team0_.id as id1_3_0_,
team0_.name as name2_3_0_
from
Team team0_
where
team0_.id=?
다음과 같이 즉시 로딩(EAGER) 방식을 사용하면 Member 조회하는 시점에 바로 Team까지 불러오는 쿼리를 날려 한꺼번에 데이터를 불러오는 것을 볼 수 있다.
지연로딩이란, 필요한 시점에 연관된 객체의 데이터를 불러오는 것이다.
@ManyToOne(fetch = FetchType.LAZY) //Team을 조회할 때 지연로딩을 사용하곘다!
JPQL로 Member 조회
Member findMember = em.createQuery("select m from Member m", Member.class).getSingleResult();
실제 SQL 코드
//Team을 조회하는 쿼리가 나가지 않음!
select
member0_.id as id1_0_,
member0_.team_id as team_id3_0_,
member0_.username as username2_0_
from
Member member0_
지연 로딩을 사용하면 Member를 조회하는 시점이 아닌 실제 Team을 사용하는 시점에 쿼리가 나가도록 할 수 있다는 장점이 있다.
위 예제의 즉시 로딩에서는 member와 연관된 Team이 1개여서 Team을 조회하는 쿼리가 나갔지만, 만약 Member를 조회하는 JPQL을 날렸는데 연관된 Team이 1000개라면? Member를 조회하는 쿼리를 하나 날렸을 뿐인데 Team을 조회하는 SQL 쿼리 1000개가 추가로 나가게 된다.
그렇기 때문에 가급적이면 기본적으로 지연로딩을 사용하는 것이 좋다.