
1. 하이버네이트 ontomany 오류(N+1오류)
1.1 영화에서 상영관을 조인 그리고 상영시간을 조인
@Query("SELECT c FROM Cinema c JOIN FETCH c.screens s
JOIN FETCH s.showtimes st WHERE c.id = :id")
Cinema mFindCinemaById(@Param("id") Long id);
1.2 에러가 발생 - ontomany를 두번 사용해서 나는 에러

2. 해결1 - 조인을 상영관까지만 함
@Query("select c from Cinema c join fetch c.screens s where c.id=:id")
Cinema mFindCinemaById(@Param("id") Long id);
나머지는 lazy로 가져오게 실행함
2.1 해결1의 테스트코드
테스트코드
@Test
public void mFindCinemaById_test(){
Long id = 1L;
Cinema cinema = adminRepository.mFindCinemaById(id);
System.out.println("영화관 정보:");
System.out.println("Cinema ID: " + cinema.getId());
System.out.println("Cinema Name: " + cinema.getName());
System.out.println(cinema.getScreens().size());
List<Screen> screens = cinema.getScreens();
System.out.println("상영관 목록:");
for (Screen screen : screens) {
System.out.println(" Screen ID: " + screen.getId());
System.out.println(" Screen Name: " + screen.getName());
System.out.println(" ------------");
List<Showtime> showtimes = screen.getShowtimes();
System.out.println("상영시간숫자 : " +showtimes.size());
System.out.println(" 상영시간 목록:");
for (Showtime showtime : showtimes) {
System.out.println(" Showtime ID: " + showtime.getId());
System.out.println(" 상영 시작 시간: " + showtime.getStartedAt());
}
}
}
2.2 해결 1의 문제발생
Hibernate:
select
c1_0.id,
c1_0.img_name,
c1_0.img_uname,
c1_0.name,
c1_0.region_id,
s1_0.cinema_id,
s1_0.id,
s1_0.name
from
cinema_tb c1_0
join
screen_tb s1_0
on c1_0.id=s1_0.cinema_id
where
c1_0.id=?
영화관 정보:
Cinema ID: 1
Cinema Name: 서면롯데시네마
5
상영관 목록:
Screen ID: 1
Screen Name: 1상영관
------------
Hibernate:
select
s1_0.screen_id,
s1_0.id,
s1_0.movie_id,
s1_0.started_at
from
showtime_tb s1_0
where
s1_0.screen_id=?
상영시간숫자 : 3
상영시간 목록:
Showtime ID: 1
상영 시작 시간: 2024-09-12 14:00:00.0
Showtime ID: 2
상영 시작 시간: 2024-09-12 16:00:00.0
Showtime ID: 3
상영 시작 시간: 2024-09-12 18:00:00.0
Screen ID: 2
Screen Name: 2상영관
------------
Hibernate:
select
s1_0.screen_id,
s1_0.id,
s1_0.movie_id,
s1_0.started_at
from
showtime_tb s1_0
where
s1_0.screen_id=?
상영시간숫자 : 1
상영시간 목록:
Showtime ID: 4
상영 시작 시간: 2024-09-12 17:00:00.0
Screen ID: 3
Screen Name: 3상영관
------------
상영시간을 계속 쿼리를 날려서 가지고 온다
추후 이로직이면 영화관안에 상영관이 5개이고 1개의 상영관이 5개의 상영시간테이블을 가지면 25번을 실행한다는 뜻이다 문제가 있다.
3.SET 사용
@NoArgsConstructor
@Entity
public class Cinema { //영화관 테이블
//TODO: 주석추가
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id ;
private String imgName;
@Column(length = 500)
private String imgUname;
private String name;
@ManyToOne(fetch = FetchType.LAZY)
private Region region;
@OneToMany(mappedBy = "cinema",fetch = FetchType.LAZY)
private List<Screen> screens;
여기서
@OneToMany(mappedBy = "cinema",fetch = FetchType.LAZY)
private List<Screen> screens;
여기 List 를 set로 바꾸면 정상작동을한다 즉
@Query("SELECT c FROM Cinema c JOIN FETCH c.screens s
JOIN FETCH s.showtimes st WHERE c.id = :id")
위에 커리문을 다시 사용이 가능하게 된다
문제는 같이사용하는 엔티티를 set으로 바꾸는건 아닌거같다
4.NativeQuery로 만든다
SELECT c.name, scr.name, st.id, st.started_at FROM cinema_tb c JOIN screen_tb scr ON c.id = scr.cinema_id JOIN showtime_tb st ON scr.id = st.screen_id
jpql을 사용하지 않고 이경우에는 네이티브로 한번에 가져온다.
Share article