Spring jpa 에서 연관관계 매핑을 할때 설정하는 문제이다
JPA 에서 데이터를 조회 할때 eager loading(즉시 로딩), lazy loading(지연 로딩) 으로 하는 두가지 방식이 있다
이 두개의 차이점은 한개의 테이블을 조회할때 그 테이블에 연관된 테이블까지 불러오냐 안 불러오냐의 차이점이다
여기서 즉시 로딩(eager)은 연관된 데이터까지 한 번에 불러오고
지연 로딩(lazy)은 필요한 시점에 연관된 데이터를 불러온다
어떻게 설정을 하냐?
@Entity
@Setter
@Getter
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "post")
public class Post {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "post_id")
private Long postId;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id")
private User user;
@Column(name = "title")
private String title;
@Column(name = "content")
private String content;
}
일단, 해당하는 테이블의 연관관계 1:N, N:1, 1:1 등등을 설정해주고 fetch 타입을 지정해준다
Fetch Type 이란?
JPA가 하나의 Entity를 조회할 때 연관관계에 있는 객체들을 어떻게 가져올 것이냐를 나타내는 설정값이다
여기에서 JPA는 ORM 기술이다
사용자가 쿼리를 직접 작성하지 않고 JPQL을 이용하여 쿼리문을 생성하기 때문에
객체와 필드를 보고 쿼리를 생성한다
즉시 로딩
- 데이터를 조회할 때 연관된 모든 객체의 데이터까지 한번에 불러오는 것
- @xxToxx(fetch = FetchType.EAGER)
@Entity
@Getter
@Setter
@Table(name = "category")
@NoArgsConstructor
public class Category {
@Id
@Column(name = "category_id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "parent_category_id")
private Category parentCategory;
@Column(name = "category_name")
private String name;
public Category(Category parentCategory, String name) {
this.parentCategory = parentCategory;
this.name = name;
}
}
이렇게 category라는 entity가 있고 부모 카테고리와 N:1의 관계를 가지고 있다고 보자
category 한개를 조회할 때 어떤 쿼리가 만들어질까 ?
Hibernate:
select c1_0.category_id,c1_0.category_name,pc1_0.category_id,pc1_0.category_name,pc1_0.parent_category_id
from category c1_0
left join category pc1_0 on pc1_0.category_id=c1_0.parent_category_id
where c1_0.category_id=?
위와 같이 즉시 로딩을 사용하게 되면 category를 조회할때 부모 카테고리 까지 불러오는 쿼리를 작성하여 한꺼번에 데이터를 불러온다
지연 로딩
- 필요한 시점에 연관된 객체의 데이터를 불러온다
- @xxToxx(fetch = FetchType.LAZY)
위에 있는 Category entity에서 FetchType 을 Lazy로 바꾼다면 어떤 쿼리가 만들어질까?
Hibernate:
select c1_0.category_id,c1_0.category_name,c1_0.parent_category_id
from category c1_0
where c1_0.category_id=?
위와 같이 부모 카테고리의 데이터까지는 불러오지 않는다
즉, 지연 로딩을 사용하면 연관된 데이터는 사용하는 시점에 쿼리가 나가도록 할 수 있다
어떤 사람들은 "어차피 가져와야 하는 데이터면 EAGER가 좋지 않냐?"라고 말하기도 한다
그러나, EAGER 로딩을 무조건적으로 사용하는 것은 바람직하지 않다
EAGER 로딩은 연관된 모든 데이터를 한 번에 가져오므로, 불필요한 데이터가 함께 로딩되어 성능 문제를 야기할 수 있다
만약 특정한 경우, 예를 들어 카테고리와 부모 카테고리가 항상 함께 사용되는 상황이라면, EAGER로 설정하여 데이터를 함께 조회하는 것이 합리적일 수 있다
그러나 해당 엔티티를 조회할 때 연관된 데이터가 당장 필요하지 않거나, 특정 시점에만 필요한 경우라면 LAZY 로딩을 사용하는 것이 좋다 이 경우에는 필요한 시점에 별도의 쿼리를 작성하여 데이터를 가져오는 것이 성능 면에서 더 유리하다
'Spring JPA' 카테고리의 다른 글
[Spring JPA] JPA N+1 문제 (1) | 2024.10.13 |
---|---|
[Spring JPA] entity의 생성일, 수정일 어떤식으로 할까 (1) | 2024.09.11 |
[Spring] DB 상태 테이블, Enum 관리 Converter 사용해보자 (1) | 2024.07.04 |
[Spring] OSIV 란? (1) | 2024.05.24 |