[resvervation/view] 영화 예매페이지
DB로 데이터 가지고 오기 시행착오 -1
isNew
miniThumnail
uploadedDate
DB 생각
처음 생각은 무작정 지역, 영화관, 영화, 날짜, 상영시간이 필요하고
지역 누르면 영화관 나오고 쭉 연결됐다 생각해서 한번에 데이터 뽑을 수 있는 쿼리를 생각했다.
select c.name, r.city, s.name, st.started_at, mt.movie_nm, mt.rating_grade from
cinema_tb c
left outer join region_tb r on c.region_id = r.id
right outer join screen_tb s on r.id = s.cinema_id
right outer join showtime_tb st on s.id = st.screen_id
left outer join movie_tb mt on st.movie_id = mt.id

아직 총 좌석, 현 남은 좌석 없다!
총 좌석은 seat 테이블에서 count해서 구하고, 남은 좌석은 티켓정보에서 빼는걸로
고민
쿼리문 사용할 때 클래스 타입을 넣고 파라미터에 클래스를 넣는데 안에 들은게 없어서 뭘 넣을지 모르겠다
예약 클래스 안에 pk, 유저fk, 예약시간이 들어가 있다 그래서 쿼리문을 골라도 담을 곳이 없다
DTO로 만든다 해도 타입이 없으니 잘 모르겠다
→ 실제 내가 해야할 클래스는 예약 클래스가 아니고 showTime 클래스 일지도 모르겠다.
showTime에 영화정보, 좌석, 시간, 영화관 등 다 들어가 있어서 필요할 것 같다 도와주셔서 감사합니다. 아직 해결못함 고민중
- 해결
쇼타임 클래스에서 작업했습니다.
세션으로 값을 보내야 할지, insert해서 좌석에 정보를 줘야 할지 로컬스토리에 넣어야 할지 고민
세션 스토리에 넣으면 사라지지만 예약때 좌석까지 선택해야 모든 것이 완성되기에 예약시 좌석 전에는 상관 없다 판단 강사님은 insert해서 하고 좌석때 update하는게 좋다 했지만 우리가 지금 짠 테이블에서는 힘들다 했다 뭐가 힘들다 했지?
그래서 굳이 정보를 저장할 필요 없이 showTime의 프라이머리키를 세션에 저장해서 좌석쪽에 전달해주자
- 해결
세션에 저장했음
한번에 많은 테이블을 join해서 jpql로 하려니까 오류남
join join하면 데이터는 많아지겠지만 JPQL로 하려니까 일단 안된다. 안 되는 것 같다
또 여러번 join하니까 IO를 너무 많이 사용한다.
- 해결
하나 하나 찾아서 pk번호 List로 만들어서 찾기
임의 데이터 만들어서 ajax로 csr연습해보기
생각변환
지역 누르면 영화관, 영화관 누르면 영화 지역 아이디만 알면 모든 것을 아는 것이 아닌
나눠서 생각해 보자!!
- 지역id선택시 영화관 나올 수 있게
- 영화관 id선택시 영화 나올 수 있게(이 부분이 제일 어려웠다. 너무 멀리 있는 정보를 받아와야 했기에)
- 영화 선택 시 날짜가 나오는데 고민이 있었다. 일단 js로 오늘 날짜 + 5 하는 걸로 결정
- 그냥 누르면 서버하고 연결 안하고 js로 오늘 날짜 + 5일을 그냥 올릴건지
- 영화 선택 시 상영시간이 있는 날짜만 나오게 할 것인지(이게 좋은게 상영시간 없는 날짜가 굳이 보일 필요가 없다 생각했다. 클릭해도 없는 날이면 안보이는게 좋지 않은가?)
- 날짜 선택 시 해당 영화와 해당 날짜에 맞는 상영시간 보여주기
- 상영시간 선택 시 확인 버튼이 나오고
- 확인 버튼 누르면 세션으로 seat페이지로 보내기
계획
.png%3Ftable%3Dblock%26id%3D12774cc6-9dcf-814a-b0f9-e98e271d82e8%26cache%3Dv2&w=1920&q=75)
.png%3Ftable%3Dblock%26id%3D12774cc6-9dcf-81e9-8672-c6dbab423643%26cache%3Dv2&w=1920&q=75)
.png%3Ftable%3Dblock%26id%3D12774cc6-9dcf-81aa-b5db-f8afe277f589%26cache%3Dv2&w=1920&q=75)
.png%3Ftable%3Dblock%26id%3D12774cc6-9dcf-8123-a280-fdcec4c89a37%26cache%3Dv2&w=1920&q=75)
.png%3Ftable%3Dblock%26id%3D12774cc6-9dcf-81d5-a55c-fb46ba426ef3%26cache%3Dv2&w=1920&q=75)
VsCode로 DB연결 없이 먼저 화면에 기능 넣어보기

임의로 정보들을 만들어 화면에 나올 수 있게 테스트 하기
영화관
let cinemaList = [`가산디지털단지`, `사상롯데시네마`, `화명CGV`, `서면롯데시네마`, `덕천메가박스`];
for (let i = 0; i < cinemaList.length; i++) {
console.log(cinemaList[i] + `<br>`);
}
영화
let movieList = [{ age: 15, title: `베리드` }, { age: 15, title: `러브로지` }, { age: 19, title: `쏘우` }, { age: 19, title: `악마를 보았다` }];
for (let i = 0; i < movieList.length; i++) {
console.log(movieList[i].age + `<br>`);
console.log(movieList[i].title + `<br>`);
}
//날짜
var today = new Date();
var date = today.getDate();//일
//현재 날짜 +1
for (let i = 0; i < 10; i++) {
console.log(date + i);
}
상영시간 + 좌석
let seatList = [{ time: `14:35`, remain: `85/90` }, { time: `18:35`, remain: `20/98` }]
for (let i = 0; i < seatList.length; i++) {
console.log(seatList[i].time + `<br>`);
console.log(seatList[i].remain + `<br>`);
}
아직 day로 하면 일요일 시작으로 0123456 으로 숫자로 나오는 것은 아는데 이 것을 요일로 바꾸는 법이 아직 미숙함
먼저 화면 뿌리고 시작할 예정
<!-- 메인 콘텐츠 -->
<div class="main__content">
<!-- 영화관 선택 -->
<div class="section">
<div class="section__title">영화관</div>
<div class="content cinema__selection">
<div onclick="cinemaLists()" class="cinema__area">
<div class="cinema__item">부산</div>
<div class="cinema__item">서울</div>
</div>
<div class="cinema__name" id="cinemas">
</div>
</div>
</div>
<!-- 영화 선택 -->
<div class="section">
<div class="section__title">영화 선택</div>
<div class="content" id="movies">
</div>
</div>
let isMovieListsExecuted = false;
// 여기서는 영화 리스트를 가지고 와야한다
let movieList = [{ age: 15, title: `베리드` }, { age: 15, title: `러브로지` }, { age: 19, title: `쏘우` }, { age: 19, title: `악마를 보았다` }];
for (let i = 0; i < movieList.length; i++) {
console.log(movieList[i].age + `<br>`);
console.log(movieList[i].title + `<br>`);
}
function movieLists() {
if (isMovieListsExecuted) return;
for (let i = 0; i < movieList.length; i++) {
$("#movies").append(makeMovies(i))
}
isMovieListsExecuted = true;
}
function makeMovies(id) {
return ` <div class="movie__item">
<img src="num_${movieList[id].age}.png" alt="rating">
<span>${movieList[id].title}</span>
</div>`
}
function cinemaLists() {
if (isCinemaListsExecuted) return;
for (let i = 0; i < cinemaList.length; i++) {
$("#cinemas").append(makeCinemas(i))
console.log(cinemaList[i] + `<br>`);
}
isCinemaListsExecuted = true;
}
function makeCinemas(id) {
return ` <div onclick="movieLists()" class="cinema__detail__item">${cinemaList[id]}</div>`
}
이런식으로 먼저 화면 클릭 시 이동되는 것을 먼저 연습함
DB로 데이터 가지고 오기 시행착오 -2
1. 지역 ssr로 뿌리기 위한 DB
select city from region_tb

2. 지역 선택 시 영화관 나올 수 있게
SELECT rt.city, ct.name
FROM REGION_TB rt
INNER JOIN cinema_tb ct ON rt.id = ct.region_id
WHERE rt.id = 2;

3. 영화관 선택 시 영화 나올 수 있게
- 영화관 id = 1일 때 상영관들
select * from cinema_tb ct
inner join screen_tb st on ct.id = st.cinema_id
where ct.id = 1

- 상영관이 1일 때 영화들
SELECT *
FROM showtime_tb st
LEFT OUTER JOIN screen_tb stb ON st.screen_id = stb.id
LEFT OUTER JOIN movie_tb m ON st.movie_id = m.id
WHERE stb.id = 1;

- 영화, 쇼타임 합치고 스크린 1236일 때 조회
SELECT *
FROM showtime_tb st
LEFT OUTER JOIN movie_tb mt ON st.movie_id = mt.id
WHERE mt.id IN (1, 2, 3, 6);
- 영화, 쇼타임 합치고 스크린 영화관 아이디 1 일 때 조회
SELECT *
FROM showtime_tb st
LEFT OUTER JOIN movie_tb mt ON st.movie_id = mt.id
WHERE mt.id IN (select st.id from cinema_tb ct
inner join screen_tb st on ct.id = st.cinema_id
where ct.id = 1);
- 이거 JPQL
SELECT st
FROM Showtime st
LEFT JOIN st.movie mt
WHERE mt.id IN (
SELECT s.id
FROM Cinema c
JOIN c.screens s
WHERE c.id = :cinemaId
)
영화관 1일 때 영화 이름, 수위
SELECT distinct mt.movie_nm, mt.rating_grade
FROM showtime_tb st
LEFT OUTER JOIN movie_tb mt ON st.movie_id = mt.id
WHERE mt.id IN (select st.id from cinema_tb ct
inner join screen_tb st on ct.id = st.cinema_id
where ct.id = 1);
문제가 있었다!
IN쿼리 안에
select st.id from cinema_tb ct
inner join screen_tb st on ct.id = st.cinema_id
where ct.id = 1
이 쿼리의 결과를 넣어야 하는데 넣으려고 하니까 못 넣겠음…
- 해결 영화관으로 상영관PK번호 찾은 것을 List에 담아서 그 결과를 showtime,영화 join한 곳에 in으로 넣어 구하자!
4. 영화 선택 시 날짜 나올 수 있게
- DB에서 조회해서 상영시간 있는 영화 날짜만 뿌리기 장점 1. 날짜 선택 화면에서 해당 영화가 있는 날짜만 보여주기에, 상영시간이 없는 필요없는 날짜는 보여주지 않음
- DB조회하지 않고 ssr로 그냥 js에서 계산해서 뿌리기 장점 1. V1이기에 먼저 화면에 뿌리는 것을 먼저 해두고 다 만든 후 손보면 또 금방함 - 채택함
5. 날짜 선택 시 상영시간 나올 수 있게
영화PK ID와 날씨를 들고 찾아야 한다
날짜를 선택해서 구할 수 있는 방법
sql
SELECT * FROM SHOWTIME_TB WHERE DAY(started_at) = 12;
JPQL
SELECT s FROM Showtime s WHERE FUNCTION('DAY', s.startedAt) = 12
또 신경써야 할 게 있다 영화 id로도 확인해야한다!
sql
SELECT * FROM SHOWTIME_TB
WHERE DAY(started_at) = 23
AND movie_id = 1;
JPQL
SELECT s FROM Showtime s
WHERE FUNCTION('DAY', s.startedAt) = 23
AND s.movieId = :movieId
json으로 정보 보내기
json
근데 이거 왜 된거지? 아직 모름
- 잘 몰랐던게 ShowtimeResponse.MoveiDTO를 받을 때 생성자 Moive movie를 넣었는데 List<Movie>로 받아야해서 고민 계속함
- 참고함 여기에서
이거 그냥
public List<ShowtimeResponse.ShowTimeDTO> 날짜보기(Long date,Long id){
List<Showtime> dats = showtimeRepository.mFindByDateIdMovieId(date,id);
List<ShowtimeResponse.ShowTimeDTO> dtos = new ArrayList<>();
for(Showtime showtime : dats){
ShowtimeResponse.ShowTimeDTO dto = new ShowtimeResponse.ShowTimeDTO(showtime);
dtos.add(dto);
}
return dtos;
}
이렇게 했으면 됐는데 이 때는 기억을 못했었음
그래서 이런식으로 했음
public List<ShowtimeResponse.MovieDTO> 영화관영화보기(Long id){
List<Screen> screens = screenRepository.mFindScreenByCinemaId(id);
List<Long> screenIds = screens.stream().map(screen -> screen.getId()).toList();
List<Showtime> showtimes = showtimeRepository.mFindByWithMovieScreenIds(screenIds);
List<Movie> moviePs = showtimes.stream().map(showtime -> showtime.getMovie()).distinct().toList();
List<ShowtimeResponse.MovieDTO> movieList = new ArrayList<>();
for(Movie movie : moviePs){
ShowtimeResponse.MovieDTO dto = ShowtimeResponse.MovieDTO.builder()
.id(movie.getId())
.movieNm(movie.getMovieNm())
.ratingGrade(movie.getRatingGrade())
.build();
movieList.add(dto);
}
return movieList;
}
일단 리포지토리
@Query("select distinct st from Showtime st left join fetch st.movie mt where st.screen.id IN :ids ")
List<Showtime> mFindByWithMovieScreenIds(@Param("ids") List<Long> ids);
서비스
public List<ShowtimeResponse.MovieDTO> 영화관영화보기(Long id){
List<Screen> screens = screenRepository.mFindScreenByCinemaId(id);
List<Long> screenIds = screens.stream().map(screen -> screen.getId()).toList();
List<Showtime> showtimes = showtimeRepository.mFindByWithMovieScreenIds(screenIds);
List<Movie> moviePs = showtimes.stream().map(showtime -> showtime.getMovie()).distinct().toList();
List<ShowtimeResponse.MovieDTO> movieList = new ArrayList<>();
for(Movie movie : moviePs){
ShowtimeResponse.MovieDTO dto = ShowtimeResponse.MovieDTO.builder()
.id(movie.getId())
.movieNm(movie.getMovieNm())
.ratingGrade(movie.getRatingGrade())
.build();
movieList.add(dto);
}
return movieList;
// List<Showtime> showtimes = showtimeRepository.mFindByScreenIds(screenIds);
// List<Movie> moviePs = showtimes.stream().map(showtime -> showtime.getMovie()).distinct().toList();
}
컨트롤러
@GetMapping("/reservation/cinema/{id}")
public ResponseEntity<?> movies(@PathVariable("id") Long id){
List<ShowtimeResponse.MovieDTO> movieList = showtimeService.영화관영화보기(id);
return ResponseEntity.ok(Resp.ok(movieList));
}
또 다른 궁금증
왜 alt=”rating” 이라 하면 사진이 안 보이고 rating 글자만 보일까?
async function movies(cinemaId){
let response = await fetch("http://localhost:8080/reservation/cinema/"+cinemaId,{
method: "get"
});
let data = await response.json();
console.log("data ", data);
console.log("body ", data.body);
$("#movie-box").empty();
for(movie of data.body){
let dom = makeMovie(movie);
$("#movie-box").append(dom);
}
}
function makeMovie(movie){
return ` <div class="movie__item">
<img src="num_${movie.ratingGrade}.png" alt="rating">
<span>${movie.movieNm}</span>`;
}
하고 json은

이런식으로

- 지역 선택 시 영화관

- 영화관 선택 시 영화 리스트

- 영화 리스트 선택 시 오늘 날짜로 +5

- 날짜 선택 시 상영시간

Share article