[Error] 하이버네이트 @OneToMany 에러 - 2 (해결) (feat. inquery)

김호정's avatar
Oct 09, 2024
[Error] 하이버네이트 @OneToMany 에러 - 2 (해결) (feat. inquery)
 
 
Join을 1번만 하고 나머지는 lazy loading으로 가져오는 방법과
Inquery를 사용해서 데이터를 가져오는 방법 두 개를 사용해 보았다.
 

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); }
 

CinemaRepository

package shop.mtcoding.filmtalk.cinema; 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; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; import shop.mtcoding.filmtalk.screen.Screen; public interface CinemaRepository extends JpaRepository<Cinema, Long> { @Query("select c from Cinema c join fetch c.screens s") List<Cinema> mFindAllWithScreen(); //@Query("SELECT c FROM Cinema c JOIN FETCH c.screens s JOIN FETCH s.showtimes st WHERE c.id = :id") @Query("select Distinct c from Cinema c join fetch c.screens s where c.id=:id") Cinema mFindByIdWithScreen(@Param("id") Long id); @Query("select c from Cinema c join fetch c.screens s where c.id=:id") Cinema mFindCinemaById(@Param("id") Long id); @Query("select c from Cinema c join fetch c.region r where c.id=:id") Cinema mFindCinemaRegionById(@Param("id") Long id); }
notion image
 
notion image
 
→ select가 2번만 실행된다.
 

2. 조인 + 레이지로딩 (Join + LazyLoading) 으로 했을 때

 
→ 역시나 select가 2번 실행된다.
→ select 하는 횟수에 대한 차이는 없음
 
 
→ DB 조회 횟수에 대한 차이는 없지만
 
데이터를 더 깔끔하게볼 수 있는건 In query를 사용했을 때인 것 같다.
 
Share article

keepgoing