트러블슈팅: 지연 로딩으로 인한 연관 관계 삭제 문제

song yuheon·2023년 10월 18일
0

Trouble Shooting

목록 보기
32/57
post-thumbnail
post-custom-banner

문제 상황


BookDonationEvent와 연관된 BookBookApplyDonation 사이의 연관 관계를 삭제하려고 할 때, java.lang.IndexOutOfBoundsException 오류가 발생했다.
디버깅을 진행한 결과 BookApplyDonation 객체가 프록시 객체로 로드된 것을 확인했습니다.


원인


  1. 지연 로딩(Lazy Loading)
    JPA는 기본적으로 연관된 엔터티를 지연 로딩으로 가져온다.
    이렇게 로드된 엔터티는 실제 엔터티가 아닌 프록시 객체로 가져와진다.
    따라서 실제 엔터티의 데이터에 접근하려고 할 때 문제가 발생할 수 있다.

  2. 프록시 객체의 특성
    프록시 객체는 실제 데이터를 가지고 있지 않기 때문에 연관 관계의 수정이나 삭제 등의 연산이 제대로 수행되지 않을 수 있다.


해결 방법


영속성 컨텍스트 안에서 실제 엔터티 객체를 로드하여 연관 관계를 수정하는 방식을 사용했다.

/**
 * 도서와 나눔 신청 간의 연관 관계 삭제
 */
int applysize = bookDonationEvent.getBookApplyDonations().size();
for (int i = applysize - 1; i >= 0; i--) {
    Book book = bookRepository.findById(bookDonationEvent.getBookApplyDonations().get(i).getBook().getBookId()).orElseThrow(
            () -> new IllegalArgumentException("해당 책이 존재하지 않습니다.")
    );
    BookApplyDonation bookApplyDonation = bookApplyDonationRepository.findById(bookDonationEvent.getBookApplyDonations().get(i).getApplyId()).orElseThrow(
            () -> new IllegalArgumentException("해당 신청이 존재하지 않습니다.")
    );
    bookApplyDonation.removeBook(book);
}

주의할 점


  1. 성능
    각 엔터티를 DB에서 다시 로드하기 위한 추가 쿼리를 수행하므로 성능에 영향을 줄 수 있다
    -> 이 후에는 패치 조인으로 작업을 해야한다.

  2. 트랜잭션
    모든 작업은 트랜잭션 내에서 수행되어야 한다.

  3. 코드 복잡성
    실제 엔터티를 로드하기 위한 추가적인 코드로 인해 복잡성이 증가할 수 있다.


profile
backend_Devloper
post-custom-banner

0개의 댓글