IJY
느리더라도 꾸준히
IJY
전체 방문자
오늘
어제
  • 분류 전체보기 (67)
    • Develop (67)
      • Java (8)
      • Go (0)
      • Test (1)
      • Web (1)
      • HTML, CSS (1)
      • TIL(Today I Learned) (18)
      • SQL (0)
      • Algorithm (27)
      • 회고 (7)
      • Troubleshooting (1)
      • Etc (3)
    • Etc (0)

블로그 메뉴

  • 홈
  • 태그
  • 방명록
  • 글쓰기

공지사항

인기 글

태그

  • API 예외 처리
  • sort
  • 재귀
  • 우테코 온보딩
  • Class
  • web
  • BufferedReader
  • 초기화
  • 소수 찾기
  • object
  • 회고
  • REST Assured
  • BufferedWriter
  • Filter
  • MVC
  • init
  • recursion
  • 12921
  • instance
  • 프로그래머스
  • 독후감
  • stream
  • 알고리즘
  • EntityTransaction
  • PostConstruct
  • Interceptor
  • Spring
  • html
  • 백준
  • java

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
IJY

느리더라도 꾸준히

Develop/Java

JPA Fetch Type

2022. 9. 9. 03:51

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
    'Develop/Java' 카테고리의 다른 글
    • Spring 기동시 bean 초기화 메서드 호출 방법
    • Java - File read 2가지 방법
    • Collection framwork
    • 제네릭(Generic)이란?
    IJY
    IJY
    개발 관련 공부한 내용을 정리하는 블로그입니다. 느리더라도 꾸준히 포스팅을 하려고 노력합니다.

    티스토리툴바