트러블슈팅

[트러블슈팅] JPA에서 default_batch_fetch_size 또는 @BatchSize 사용 시 LazyInitializationException이 발생하는 문제

2022. 10. 5. 23:27
목차
  1. 개요
  2. 해결
  3. 참고

개요

1:N 관계에서 1을 기준으로 연관된 데이터를 모두 가져오고자 하는 상황에서 @BatchSize를 통해 Batch Fetching을 시도했으나 LazyInitializationException이 발생했다. 

 

대략적인 코드는 다음과 같다.

 

Order - 주문(1)

@Entity
class Order(
    @Id
    var orderKey: Long? = null,

    @BatchSize(size = 100)
    @OneToMany(mappedBy = "order")
    var options: MutableList<Option> = mutableListOf(),
    
    // 생략..
)

 

Option - 옵션(N)

@Entity
class Option(
    @Id
    var optionNo: Long? = null,
    
    @JoinColumn(name = "ORDER_KEY")
    @ManyToOne(fetch = FetchType.LAZY)
    var orders: Order? = null,
    
    // 생략...
}

 

OrderRepository

interface OrderRepository : JpaRepository<Order, Long> {

    @Query("SELECT o FROM Order o WHERE o.orderKey IN :orderKeys")
    fun findOrders(orderKeys: List<Long>): List<Order>
}

 

통합 테스트를 수행하니 다음과 같이 에러가 발생했는데.. (참고로 별도로 @Transactional는 붙이지 않은 상태였다)

 

 

해결

원인은 간단했다. Batch Fetching을 시도하는 시점이 연관관계를 맺고 있는 하위 엔티티를 로딩하는 시점이기 때문이다. 즉, Order를 SELECT하는 시점에 바로 IN 쿼리를 통해 연관된 Option을 가져오는 것이 아니고, 실제로 Option이 참조되는 시점에 IN 쿼리가 발생한다는 의미이다.

 

이는 곧 트랜잭션(정확히는 영속성 컨텍스트) 안에서만 Batch Fetching이 이루어질 수 있다는 의미인데, 나는 해당 테스트 코드에 별도로 트랜잭션을 걸어놓지 않았기 때문에 LazyInitializationException이 발생한 것이다.

 

@Transactional 어노테이션을 붙이면 정상적으로 테스트가 통과하는 것을 알 수 있다.

당연한 말이지만 서비스에서 해당 레포지토리 메서드를 호출할 때도 동일하게 트랜잭션이 걸려 있어야 N에 해당하는 객체의 값을 가져올 수 있다.

 

 

참고

https://jojoldu.tistory.com/414

저작자표시 비영리 (새창열림)

'트러블슈팅' 카테고리의 다른 글

[트러블슈팅] org.springframework.dao.InvalidDataAccessApiUsageException: javax.persistence.Query.executeUpdate requires active transaction  (0) 2022.11.23
[트러블 슈팅] IO 오류: Socket read interrupted (SQL Error: 17002, SQLState: 08006)  (1) 2022.11.01
[트러블슈팅] 테스트 코드에서 @Slf4j cannot find symbol 에러  (0) 2022.08.15
[트러블슈팅] CORS 설정 시 allowedOrigins 에러  (0) 2022.07.25
[트러블슈팅] IntelliJ Build Error: java.lang.AbstractMethodError  (0) 2022.07.15
  1. 개요
  2. 해결
  3. 참고
'트러블슈팅' 카테고리의 다른 글
  • [트러블슈팅] org.springframework.dao.InvalidDataAccessApiUsageException: javax.persistence.Query.executeUpdate requires active transaction
  • [트러블 슈팅] IO 오류: Socket read interrupted (SQL Error: 17002, SQLState: 08006)
  • [트러블슈팅] 테스트 코드에서 @Slf4j cannot find symbol 에러
  • [트러블슈팅] CORS 설정 시 allowedOrigins 에러
코택
코택
코택
TaxFree
코택
전체
오늘
어제
  • 분류 전체보기 (369)
    • Spring (29)
      • Spring (18)
      • 스프링 핵심 원리 - 고급편 (11)
    • Spring Batch (4)
    • JPA (4)
    • CS (89)
      • 자료구조 (2)
      • 네트워크 (5)
      • 운영체제 (1)
      • 데이터베이스 (4)
      • SQL (7)
      • 알고리즘 이론 (4)
      • 알고리즘 문제 풀이 (66)
    • 웹 (28)
      • React.js (4)
      • Next.js (1)
      • Node.js (14)
      • FastAPI (4)
      • Django (5)
    • 프로그래밍 언어 (45)
      • Python (5)
      • Java + Kotlin (29)
      • JavaScript + TypeScript (11)
    • 테스트코드 (26)
      • ATDD, 클린 코드 with Spring (4)
      • 이규원의 현실 세상의 TDD: 안정감을 주는 코드.. (20)
    • 인프라 (6)
      • AWS (2)
      • Kubernetes (4)
    • 트러블슈팅 (25)
    • 책 (89)
      • Effective Java (54)
      • Effective Kotlin (14)
      • 도메인 주도 개발 시작하기: DDD 핵심 개념 정.. (11)
      • 웹 프로그래머를 위한 데이터베이스를 지탱하는 기술 (6)
      • 도메인 주도 설계 첫걸음 (4)
    • Git (10)
    • 회고 (5)
    • etc (8)

블로그 메뉴

  • 홈
  • 방명록
  • 관리
  • GitHub
  • LinkedIn

공지사항

  • 스킨 관련

인기 글

태그

  • 깊이 우선 탐색
  • 브루트포스
  • http
  • atdd
  • BOJ
  • 그래프
  • fastapi
  • dp
  • Shortest Path
  • Git
  • 장고
  • 백준
  • 파이썬
  • 그래프 탐색
  • mysql

최근 댓글

최근 글

hELLO · Designed By 정상우.
코택
[트러블슈팅] JPA에서 default_batch_fetch_size 또는 @BatchSize 사용 시 LazyInitializationException이 발생하는 문제
상단으로

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.