Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
implementation 'org.redisson:redisson-spring-boot-starter:3.43.0'
compileOnly 'org.projectlombok:lombok'
developmentOnly 'org.springframework.boot:spring-boot-docker-compose'
runtimeOnly 'com.mysql:mysql-connector-j'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@
import org.springframework.web.bind.annotation.*;

import com.movie.app.domain.Movie;
import com.movie.app.domain.MovieRepository;
import com.movie.app.domain.MovieRequestDto;
import com.movie.app.domain.TicketingRequestDto;
import com.movie.app.service.MovieService;

import jakarta.validation.constraints.Size;
import lombok.RequiredArgsConstructor;
Expand All @@ -15,7 +16,7 @@
@RestController
public class MovieRestController {

private final MovieRepository movieRepository;
private final MovieService movieService;

@GetMapping("/api/movies")
public List<Movie> getMovies(
Expand All @@ -24,18 +25,21 @@ public List<Movie> getMovies(
@RequestParam(required=false) String genre) {

if(genre != null) {
return movieRepository.findByGenre(genre);
return movieService.getMoviesByGenre(genre);
} else if (title != null) {
return movieRepository.findByTitle(title);
return movieService.getMoviesByTitle(title);
} else {
return movieRepository.findAll();
return movieService.getMoviesAll();
}
}

@PostMapping("/api/movies")
public Movie postMovies(@RequestBody MovieRequestDto requestDto) {
Movie movie = new Movie(requestDto);
movieRepository.save(movie);
return movie;
return movieService.postMovie(requestDto);
}

@PutMapping("/api/ticketing/{id}")
public Movie ticketingMovie(@PathVariable Long id, @RequestBody TicketingRequestDto requestDto) {
return movieService.ticketing(id ,requestDto);
}
}
25 changes: 23 additions & 2 deletions app/src/main/java/com/movie/app/domain/Movie.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.movie.app.domain;

import java.time.LocalTime;
import java.util.List;

import jakarta.persistence.Column;
Expand All @@ -14,6 +15,9 @@
@NoArgsConstructor
@Entity(name="Movie")
public class Movie extends Timestamped{

private static final int MAX_SEATS = 25;

@GeneratedValue(strategy = GenerationType.AUTO)
@Id
private Long id;
Expand All @@ -40,7 +44,14 @@ public class Movie extends Timestamped{
private String theater;

@Column
private List<String> screeningSchedule;
private LocalTime screenStartTime;

@Column
private LocalTime screenEndTime;

@Column
private Boolean[] seats = new Boolean[MAX_SEATS];
Comment on lines +52 to +53

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

혹시 이 부분 테스트 해보셨을까요?
boolean 배열이 디비에 저장되기 위해선 적절한 변환 과정이 선언되어야 할듯 합니다.



public Movie(MovieRequestDto requestDto) {
this.title = requestDto.getTitle();
Expand All @@ -50,6 +61,16 @@ public Movie(MovieRequestDto requestDto) {
this.runningTime = requestDto.getRunningTime();
this.genre = requestDto.getGenre();
this.theater = requestDto.getTheater();
this.screeningSchedule = requestDto.getScreeningSchedule();
}

public void updateSeats(List<Integer> wantedSeats) {
if(this.seats == null) {
this.seats = new Boolean[MAX_SEATS];
}

for (int i=0; i<wantedSeats.size(); i++) {
int val= wantedSeats.get(i);
this.seats[val]=true;
}
}
}
10 changes: 10 additions & 0 deletions app/src/main/java/com/movie/app/domain/TicketingRequestDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.movie.app.domain;

import java.util.List;

import lombok.Getter;

@Getter
public class TicketingRequestDto {
private List<Integer> seats;
}
41 changes: 40 additions & 1 deletion app/src/main/java/com/movie/app/service/MovieService.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
package com.movie.app.service;

import java.util.List;
import java.util.concurrent.TimeUnit;

import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.movie.app.domain.Movie;
import com.movie.app.domain.MovieRepository;
import com.movie.app.domain.MovieRequestDto;
import com.movie.app.domain.TicketingRequestDto;

import lombok.RequiredArgsConstructor;

Expand All @@ -15,6 +21,7 @@
public class MovieService {

private final MovieRepository movieRepository;
private final RedissonClient redissonClient;

@Cacheable(value = "Movies", key = "#title", cacheManager = "contentCacheManager")
public List<Movie> getMoviesByTitle(String title) {
Expand All @@ -27,8 +34,40 @@ public List<Movie> getMoviesByGenre(String genre) {
}

@Cacheable(value = "Movies", key = "all", cacheManager = "contentCacheManager")
public List<Movie> getMoviesByGenre() {
public List<Movie> getMoviesAll() {
return movieRepository.findAll();
}

public Movie postMovie(MovieRequestDto requestDto) {
Movie movie = new Movie(requestDto);
movieRepository.save(movie);
return movie;
}

@Transactional
public Movie ticketing(Long id, TicketingRequestDto requestDto) {
Movie movie = movieRepository.findById(id).orElseThrow(
() -> new NullPointerException("There is no id at DB.")
);

if(movie==null) {
return movie;
}
Comment on lines +49 to +55

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Movie movie = movieRepository.findById(id).orElseThrow(
() -> new NullPointerException("There is no id at DB.")
);
if(movie==null) {
return movie;
}
Movie movie = movieRepository.findById(id).orElseThrow(
() -> new NullPointerException("There is no id at DB.")
);

movie에 대해 orElseThrow를 하셨다면 movie가 null일 수는 없겠네요!
if 조건문은 없어도 되지 않을까요?ㅎㅎ


RLock lock = redissonClient.getLock(id.toString());

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

영화 전체에 대한 잠금이 걸려있네요!
영화 - 상영관 - 좌석 (5x5)
좌석은 상영관 별로 25개씩 있고, 상영관은 여러개 존재할 수 있어요.
잠금을 여러 개로 나눈다면 사용자가 덜 기다릴 수도 있지 않을까요?

try {
boolean acquireLock = lock.tryLock(10, 1, TimeUnit.SECONDS);
if (!acquireLock) {
System.out.println("Lock get fail");
return movie;
}
Comment on lines +60 to +63

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

예약이 실패됐다 라는 내용이 사용자에게 전달되려면 어떻게 해야 할까요?

movie.updateSeats(requestDto.getSeats());
} catch (InterruptedException e) {
} finally {
lock.unlock();
}

return movie;
}

}
Loading