inblog logo
|
keepgoing

    [Project] OneToMany 여러개 사용할 때 해결법

    김호정's avatar
    김호정
    Sep 17, 2024
    [Project] OneToMany 여러개 사용할 때 해결법
    Contents
    1. In query 로 했을 때2. 조인 + 레이지로딩 으로 했을 때
     
     

    1. In query 로 했을 때

    CinemaRepositoryTest

    @Test public void mFindCinemaById_test(){ Long id = 1L; Cinema cinema = cinemaRepository.mFindCinemaById(id); // 여기에 id List로 넣을 수 있다. List<Screen> screen1 = cinema.getScreens(); List<Showtime> showtimes1 = screen1.get(0).getShowtimes(); //screen1. //System.out.println(showtimes1.size()); // 이거하면 여기서 lazyLoading 발생 // System.out.println(showtimes1.getFirst().getId()); // 1 // System.out.println(showtimes1.getLast().getId()); // 2 System.out.println("영화관 정보:"); System.out.println("Cinema ID: " + cinema.getId()); System.out.println("Cinema Name: " + cinema.getName()); System.out.println(cinema.getScreens().size()); // 3 List<Screen> screens = cinema.getScreens(); List<Long> screenIds = screens.stream().map(screen -> screen.getId()).toList(); // stream -> screen의 id를 배열에 담음 System.out.println("screenIds : " + screenIds); // [1, 2, 3] List<Showtime> showtimes = showtimeRepository.findByScreenIds(screenIds); // 상영관들 for (Screen screen : screens) { System.out.println(" Screen ID: " + screen.getId()); System.out.println(" Screen Name: " + screen.getName()); System.out.println(" ------------"); for (Showtime showtime : showtimes) { System.out.println(" Showtime ID: " + showtime.getId()); System.out.println(" 상영 시작 시간: " + showtime.getStartedAt()); } } }
     

    showtimeRepository

    package shop.mtcoding.filmtalk.showtime; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; import java.util.List; import java.util.Optional; public interface ShowtimeRepository extends JpaRepository<Showtime,Long> { @Query("select st from Showtime st join fetch st.movie m left join fetch st.screen sc where st.id=:id") Showtime mFindById(@Param("id") Long id); @Query("select s from Showtime s where s.screen.id in :screenIds") List<Showtime> findByScreenIds(@Param("screenIds") List<Long> screenIds); }
     
     
    notion image
     
    → 2번만 select 실행됨
     
    notion image
     
    그리고 아래에 select 안치고 잘 나옴
     

    2. 조인 + 레이지로딩 으로 했을 때

    → 역시나 select 2번
    → select 하는 횟수에 대한 차이는 없음
     
    → 데이터를 더 깔끔하게볼 수 있는건 In query를 사용했을 때인 것 같음
     
    참고 :
    MultipleBagFetchException 발생시 해결 방법
    JPA의 N+1 문제에 대한 해결책으로 Fetch Join을 사용하다보면 자주 만나는 문제가 있습니다. 바로 MultipleBagFetchException 입니다. 이 문제는 2개 이상의 OneToMany 자식 테이블에 Fetch Join을 선언했을때 발생합니다. OneToOne, ManyToOne과 같이 단일 관계의 자식 테이블에는 Fetch Join을 써도 됩니다 이 문제에 대한 해결책으로 보통 2가지를 언급하는데요. 자식 테이블 하나에만 Fetch Join을 걸고 나머진 Lazy Loading로 모든 자식 테이블을 다 Lazy Loading으로 이럴 경우 성능상 이슈가 아무래도 해결되는게 아니다 보니, 좀 더 좋은 방법을 소개드리겠습니다. 모든 코드는 Github에 있습니다. 1. 문제 상황 One..
    MultipleBagFetchException 발생시 해결 방법
    https://jojoldu.tistory.com/457
    MultipleBagFetchException 발생시 해결 방법
    Share article

    keepgoing

    RSS·Powered by Inblog