✔ 깃허브 소스코드
✔ Udemy 강의영상
Fetch Type은 JPA가 하나의 엔티티를 조회할 때, 연관 관계에 있는 객체들을 어떻게 가져올 것이냐를 나타내는 설정값입니다.
Fetch Type은 크게 Eager
와 Lazy
두 가지의 전략이 있습니다. Eager
전략은 엔티티를 조회할 때, 연관 관계에 있는 엔티티도 함께 가져오고, 반대로 Lazy
전략은 연관 관계 엔티티를 참조할 때 그때서야 가져오게 됩니다.
일대일 연관관계를 가지는 학생(Student) 엔티티와 여권(Passport) 엔티티를 가지고 실행되는 쿼리문을 비교해 보겠습니다.
@Entity
@Table(name = "students")
@Getter
@Builder
@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Student {
@Id
@GeneratedValue
private Long id;
@Setter
@Column(name = "name", nullable = false, length = 100)
private String name;
@OneToOne(fetch = FetchType.LAZY)
//@OneToOne(fetch = FetchType.EAGER)
private Passport passport;
@UpdateTimestamp
@Column(name = "updated_date")
private LocalDateTime updatedDate;
@CreationTimestamp
@Column(name = "created_date")
private LocalDateTime createdDate;
@Override
public String toString() {
return String.format("Student[%s]", this.name);
}
}
@Entity
@Table(name = "passports")
@Getter
@Builder
@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Passport {
@Id
@GeneratedValue
private Long id;
@Setter
@Column(name = "number", nullable = false, length = 100)
private String number;
@OneToOne(mappedBy = "passport")
private Student student;
@UpdateTimestamp
@Column(name = "updated_date")
private LocalDateTime updatedDate;
@CreationTimestamp
@Column(name = "created_date")
private LocalDateTime createdDate;
@Override
public String toString() {
return String.format("Passport[%s]", this.number);
}
}
아래의 테스트 코드를 실행해 보면 결과는 다음과 같습니다.
@Test
@Transactional
public void retrieveStudentAndPassportDetails() {
Student student = entityManager.find(Student.class, 20001L);
logger.info(String.format("Student[%s]", student.getName()));
logger.info(String.format("Passport[%s]", student.getPassport().getNumber()));
}
⬇ Lazy Fetch 쿼리 결과 ⬇
Student 엔티티를 조회할 때, Student 정보만 조회를 하고 getter로 연관 관계 엔티티인 Passport를 참조할 때 그때서야 Passport 정보를 조회합니다.
⬇ Eager Fetch 쿼리 결과 ⬇
Student 엔티티를 조회할 때, left outer join으로 Passport 정보도 함께 조회합니다.