JPA를 사용 시 어노테이션을 사용하여 객체 간 연관관계를 지정하게 되는데, 이때 옵셔널로 설정할 수 있는 항목 중 fetch라는 키워드가 등장하게 된다.
(JPQL에서도 fetch join 이라는 단어가 등장하게 되는데, fetch 전략과 fetch join은 다른 내용)
Fetch는 간단하게 말하자면 로딩 전략이라고 보면 된다.
즉, 연관관계로 지정되어 있는 객체에 대한 정보를 언제 로드할 것인가?에 대한 내용이라고 볼 수 있다.
그리고 이때 사용되는 fetch type에는 EAGER, LAZY 총 2가지가 존재한다.
그럼 이 2가지의 차이점은 무엇인가?
EAGER (즉시 로딩)
객체에 대한 데이터 조회 즉시 연관관계 매핑이 되어있는 객체의 정보 또한 조회하는 방식
즉, 연관관계가 있는 모든 데이터를 즉시 조회하여 사용해야 하는 경우에 사용하는 방식
장점으로는 데이터 조회 후 해당 객체에 대한 모든 데이터의 사용이 가능하다는 점
단점으로는 불필요한 데이터 조회가 발생할 수 있다는 점 (리소스 소모가 크다 = 성능 저하 발생 가능)
LAZY (지연 로딩)
객체에 대한 데이터 조회 시 연관관계 매핑이 되어있는 객체에 대한 정보를 즉시 조회하지 않고, 프록시 객체를 생성하여 대체
이후 연관관계 매핑이 되어있는 객체의 정보를 사용하려고 할 때 해당 객체의 정보를 조회하여 사용하는 방식
장점으로는 데이터 조회 후 연관관계 매핑이 되어있는 객체에 대한 정보를 사용하지 않는다면 조회를 하지 않기 때문에 리소스 소모가 적다는 점
단점으로는 트랜잭션으로 동작 시 트랜잭션이 종료된 이후 해당 객체에 연관관계 매핑되어있는 객체를 사용하려는 경우 LazyInitializationException 예외가 발생하며 데이터를 사용하지 못하는 문제 발생 (해당 예외가 발생하는 자세한 이유는 "JPA에 대한 끄적임"의 "영속성 컨텍스트" 부분 참고)
위와 같은 에러가 발생한다면 해당 객체에 대한 fetch 설정을 EAGER로 지정하거나, 동일한 트랜잭션 내에서 기능이 수행될 수 있도록 해주어야 한다.
하지만 해당 객체 내부에 OneToMany 또는 ManyToMany로 연관관계 매핑이 되어있는 객체가 2개 이상인 경우, 2개 이상을 EAGER로 설정 시 MultipleBagFetchException 예외로 인한 에러가 발생하게 된다.
MultipleBagFetchException
해당 예외의 경우, JPA에서 SQL의 join문을 사용하여 데이터를 조회하게 되는데 N*M 방식으로 조회를 하게 된다.
이때, 2개 이상의 List 타입의 객체를 조회하고자 한다면 N*M*L 방식으로 조회를 하게 되면서 카티션 곱 문제가 발생할 수 있게 된다.
따라서 이러한 문제를 사전에 방지하고자 이러한 예외처리를 해두었다고 보면 된다.
또한 Bag이란 Hibernate에서 Java의 속성 타입을 JDBC의 타입에 매핑 시키기 위한 용도로 사용하는 타입 중 하나로써 Set과 같이 순서가 없고 List와 같이 중복을 허용하는 자료구조이며 Java의 Collection framwork에는 Bag 타입이 존재하지 않기에 List를 Bag으로 사용하게 된다.
그렇기 때문에 List 타입을 Set 타입으로 변경하게 된다면 해당 예외가 발생하지 않는다.
추가로 해당 예외는 N+1 문제를 해결하기 위해 Fetch join을 할 때에도 발생할 수 있다.
Default type
각각의 연관관계에 따른 fetch의 기본 설정은 다음과 같다.
OneToOne : EAGER
ManyToOne : EAGER
OneToMany : LAZY
ManyToMany : LAZY
간단하게 보자면 해당 객체와 연관관계가 1로 이루어진 관계라면 EAGER, N으로 이루어진 관계라면 LAZY가 기본 설정
결론으로는 성능을 위해서라도 특별한 경우가 아니라면 LAZY 방식을 사용하는 것이 좋다.
'Develop > Java' 카테고리의 다른 글
Spring 기동시 bean 초기화 메서드 호출 방법 (0) | 2022.11.29 |
---|---|
Java - File read 2가지 방법 (0) | 2022.11.29 |
Collection framwork (0) | 2022.07.26 |
제네릭(Generic)이란? (0) | 2022.07.25 |
Java 클래스 검색법 (0) | 2022.07.25 |