-
Notifications
You must be signed in to change notification settings - Fork 132
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Spring MVC + JDBC + CORE] 김민창 미션 제출합니다. #368
base: idle2534
Are you sure you want to change the base?
Changes from all commits
428f452
53b30fc
a54d75e
a261f8e
61979fa
4b3adbe
00bd5cb
cd44f98
368622c
e72642e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
package roomescape.controller; | ||
|
||
import java.net.URI; | ||
import java.util.List; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.stereotype.Controller; | ||
import org.springframework.validation.annotation.Validated; | ||
import org.springframework.web.bind.annotation.DeleteMapping; | ||
import org.springframework.web.bind.annotation.ExceptionHandler; | ||
import org.springframework.web.bind.annotation.GetMapping; | ||
import org.springframework.web.bind.annotation.PathVariable; | ||
import org.springframework.web.bind.annotation.PostMapping; | ||
import org.springframework.web.bind.annotation.RequestBody; | ||
import roomescape.domain.Reservation; | ||
import roomescape.domain.Reservation.NotFoundReservationException; | ||
import roomescape.dto.ReservationRequestDto; | ||
import roomescape.service.ReservationService; | ||
|
||
@Controller | ||
@RequiredArgsConstructor | ||
public class ReservationController { | ||
private final ReservationService reservationService; | ||
|
||
@GetMapping("/reservation") | ||
public String reservation() { | ||
return "new-reservation"; | ||
} | ||
|
||
@GetMapping("/reservations") | ||
public ResponseEntity<List<Reservation>> reservations() { | ||
List<Reservation> reservations = reservationService.getReservations(); | ||
return ResponseEntity.ok(reservations); | ||
} | ||
|
||
@PostMapping("/reservations") | ||
public ResponseEntity<Reservation> addReservation(@RequestBody @Validated ReservationRequestDto reservationRequestDto) { | ||
try { | ||
Long.parseLong(reservationRequestDto.getTime()); | ||
} catch (NumberFormatException e) { | ||
return ResponseEntity.badRequest().build(); | ||
} | ||
|
||
Reservation reservation = reservationService.addReservation(reservationRequestDto); | ||
return ResponseEntity | ||
.created(URI.create("/reservations/" + reservation.getId())) | ||
.body(reservation); | ||
} | ||
|
||
@DeleteMapping("/reservations/{id}") | ||
public ResponseEntity<Reservation> deleteReservation(@PathVariable Long id) { | ||
reservationService.removeReservation(id); | ||
return ResponseEntity.noContent().build(); | ||
} | ||
|
||
@ExceptionHandler(NotFoundReservationException.class) | ||
public ResponseEntity<Void> handleException(NotFoundReservationException e) { | ||
return ResponseEntity.badRequest().build(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
package roomescape.controller; | ||
|
||
import java.net.URI; | ||
import java.util.List; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.stereotype.Controller; | ||
import org.springframework.ui.Model; | ||
import org.springframework.web.bind.annotation.DeleteMapping; | ||
import org.springframework.web.bind.annotation.GetMapping; | ||
import org.springframework.web.bind.annotation.PathVariable; | ||
import org.springframework.web.bind.annotation.PostMapping; | ||
import org.springframework.web.bind.annotation.RequestBody; | ||
import roomescape.domain.Time; | ||
import roomescape.dto.TimeRequestDto; | ||
import roomescape.service.TimeService; | ||
|
||
@Controller | ||
@RequiredArgsConstructor | ||
public class TimeController { | ||
|
||
private final TimeService timeService; | ||
|
||
@GetMapping("/time") | ||
public String time() { | ||
return "time"; | ||
} | ||
|
||
@GetMapping("/times") | ||
public ResponseEntity<List<Time>> getTimes() { | ||
List<Time> times = timeService.getTimes(); | ||
return ResponseEntity.ok(times); | ||
} | ||
|
||
@PostMapping("/times") | ||
public ResponseEntity<Time> times(@RequestBody TimeRequestDto timeRequestDto) { | ||
Time time = timeService.addTime(timeRequestDto); | ||
return ResponseEntity | ||
.created(URI.create("/times/" + time.getId())) | ||
.body(time); | ||
} | ||
|
||
@DeleteMapping("/times/{id}") | ||
public ResponseEntity<Time> deleteTime(@PathVariable Long id) { | ||
timeService.removeTime(id); | ||
return ResponseEntity.noContent().build(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
package roomescape.dao; | ||
|
||
import java.sql.PreparedStatement; | ||
import java.util.List; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.jdbc.core.JdbcTemplate; | ||
import org.springframework.jdbc.support.GeneratedKeyHolder; | ||
import org.springframework.jdbc.support.KeyHolder; | ||
import org.springframework.stereotype.Repository; | ||
import roomescape.domain.Reservation; | ||
import roomescape.domain.Time; | ||
import roomescape.dto.ReservationRequestDto; | ||
|
||
@Repository | ||
@RequiredArgsConstructor | ||
public class ReservationDao { | ||
|
||
private final JdbcTemplate jdbcTemplate; | ||
|
||
public List<Reservation> findAll() { | ||
return jdbcTemplate.query("SELECT " | ||
+ "r.id AS reservation_id, " | ||
+ "r.name, " | ||
+ "r.date, " | ||
+ "t.id AS time_id, " | ||
+ "t.time AS time_value " | ||
+ "FROM reservation AS r INNER JOIN time AS t ON r.time_id = t.id", (rs, rowNum) -> | ||
new Reservation( | ||
rs.getLong("reservation_id"), | ||
rs.getString("name"), | ||
rs.getString("date"), | ||
new Time(rs.getLong("time_id"), rs.getString("time_value")) | ||
)); | ||
} | ||
|
||
public Reservation save(ReservationRequestDto reservationRequestDto) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Dao를 만드셨군요!! Dto랑 Dao는 무엇인지? |
||
KeyHolder keyHolder = new GeneratedKeyHolder(); | ||
jdbcTemplate.update(connection -> { | ||
PreparedStatement ps = connection.prepareStatement( | ||
"INSERT INTO reservation (name, date, time_id) VALUES (?, ?, ?)", | ||
new String[]{"id"} | ||
); | ||
ps.setString(1, reservationRequestDto.getName()); | ||
ps.setString(2, reservationRequestDto.getDate()); | ||
ps.setLong(3, Long.parseLong(reservationRequestDto.getTime())); | ||
return ps; | ||
}, keyHolder); | ||
|
||
return new Reservation(keyHolder.getKey().longValue(), reservationRequestDto.getName(), reservationRequestDto.getDate()); | ||
} | ||
|
||
public int delete(Long id) { | ||
return jdbcTemplate.update("DELETE FROM reservation WHERE id = ?", id); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
package roomescape.dao; | ||
|
||
import java.sql.PreparedStatement; | ||
import java.util.List; | ||
import java.util.Optional; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.dao.EmptyResultDataAccessException; | ||
import org.springframework.jdbc.core.JdbcTemplate; | ||
import org.springframework.jdbc.support.GeneratedKeyHolder; | ||
import org.springframework.jdbc.support.KeyHolder; | ||
import org.springframework.stereotype.Repository; | ||
import roomescape.domain.Time; | ||
import roomescape.dto.TimeRequestDto; | ||
|
||
@Repository | ||
@RequiredArgsConstructor | ||
public class TimeDao { | ||
private final JdbcTemplate jdbcTemplate; | ||
|
||
public List<Time> findAll() { | ||
return jdbcTemplate.query("SELECT * FROM time", (rs, rowNum) -> | ||
new Time( | ||
rs.getLong("id"), | ||
rs.getString("time") | ||
)); | ||
} | ||
|
||
public Optional<Time> findById(Long id) { | ||
try { | ||
Time time = jdbcTemplate.queryForObject("SELECT * FROM time WHERE id = (?)", (rs, rowNum) -> | ||
new Time( | ||
rs.getLong("id"), | ||
rs.getString("time")), | ||
id); | ||
return Optional.of(time); | ||
} catch (EmptyResultDataAccessException e) { | ||
return Optional.empty(); | ||
} | ||
} | ||
|
||
public Time save(TimeRequestDto timeRequestDto) { | ||
KeyHolder keyHolder = new GeneratedKeyHolder(); | ||
jdbcTemplate.update(connection -> { | ||
PreparedStatement ps = connection.prepareStatement( | ||
"INSERT INTO time (time) VALUES (?)", | ||
new String[] {"id"} | ||
); | ||
ps.setString(1, timeRequestDto.getTime()); | ||
return ps; | ||
}, keyHolder); | ||
|
||
return new Time(keyHolder.getKey().longValue(), timeRequestDto.getTime()); | ||
} | ||
|
||
public int delete(Long id) { | ||
return jdbcTemplate.update("DELETE FROM time WHERE id = ?", id); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
package roomescape.domain; | ||
|
||
import lombok.AllArgsConstructor; | ||
import lombok.Getter; | ||
import lombok.NoArgsConstructor; | ||
import lombok.Setter; | ||
|
||
@AllArgsConstructor | ||
@NoArgsConstructor | ||
@Getter | ||
@Setter | ||
public class Reservation { | ||
public static class NotFoundReservationException extends RuntimeException{} | ||
|
||
private Long id; | ||
private String name; | ||
private String date; | ||
private Time time; | ||
|
||
public Reservation(Long id, String name, String date) { | ||
this.id = id; | ||
this.name = name; | ||
this.date = date; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package roomescape.domain; | ||
|
||
import lombok.AllArgsConstructor; | ||
import lombok.Getter; | ||
import lombok.NoArgsConstructor; | ||
import lombok.Setter; | ||
|
||
@AllArgsConstructor | ||
@NoArgsConstructor | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. AllArgsConstructor와 NoArgsConstructor 둘 모두 필요한 생성자인가요?? |
||
@Getter | ||
@Setter | ||
public class Time { | ||
public static class NotFoundTimeException extends RuntimeException {} | ||
|
||
Long id; | ||
|
||
String time; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package roomescape.dto; | ||
|
||
import jakarta.validation.constraints.NotBlank; | ||
import lombok.Getter; | ||
|
||
@Getter | ||
public class ReservationRequestDto { | ||
|
||
@NotBlank | ||
private String name; | ||
|
||
@NotBlank | ||
private String date; | ||
|
||
@NotBlank | ||
private String time; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package roomescape.dto; | ||
|
||
import jakarta.validation.constraints.NotBlank; | ||
import lombok.AllArgsConstructor; | ||
import lombok.Getter; | ||
import lombok.NoArgsConstructor; | ||
|
||
@AllArgsConstructor | ||
@NoArgsConstructor | ||
@Getter | ||
public class TimeRequestDto { | ||
|
||
private String time; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package roomescape.service; | ||
|
||
import java.util.List; | ||
import roomescape.domain.Reservation; | ||
import roomescape.dto.ReservationRequestDto; | ||
|
||
public interface ReservationService { | ||
|
||
List<Reservation> getReservations(); | ||
|
||
Reservation addReservation(ReservationRequestDto reservationRequestDto); | ||
|
||
void removeReservation(Long id); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ReservationService와 ServiceImpl을 나누셨군요. 그렇게 구현하신 이유가 있을까요?? |
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
package roomescape.service; | ||
|
||
import java.util.List; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.stereotype.Service; | ||
import roomescape.dao.ReservationDao; | ||
import roomescape.dao.TimeDao; | ||
import roomescape.domain.Reservation; | ||
import roomescape.domain.Reservation.NotFoundReservationException; | ||
import roomescape.domain.Time; | ||
import roomescape.dto.ReservationRequestDto; | ||
|
||
@Service | ||
@RequiredArgsConstructor | ||
public class ReservationServiceImpl implements ReservationService { | ||
|
||
private final ReservationDao reservationDao; | ||
private final TimeDao timeDao; | ||
|
||
@Override | ||
public List<Reservation> getReservations() { | ||
return reservationDao.findAll(); | ||
} | ||
|
||
@Override | ||
public Reservation addReservation(final ReservationRequestDto reservationRequestDto) { | ||
Reservation reservation = reservationDao.save(reservationRequestDto); | ||
Time time = timeDao.findById(Long.parseLong(reservationRequestDto.getTime())).orElseThrow(); | ||
reservation.setTime(time); | ||
return reservation; | ||
} | ||
|
||
@Override | ||
public void removeReservation(final Long id) { | ||
if (reservationDao.delete(id) == 0) | ||
throw new NotFoundReservationException(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package roomescape.service; | ||
|
||
import java.util.List; | ||
import roomescape.domain.Time; | ||
import roomescape.dto.TimeRequestDto; | ||
|
||
public interface TimeService { | ||
|
||
List<Time> getTimes(); | ||
|
||
Time addTime(TimeRequestDto timeRequestDto); | ||
|
||
void removeTime(Long id); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
java 17부터는 여러 라인의 문자열을 나타낼 떄
"""
"""
로 감쌀 수 있는 문법이 있어요 한번 확인해보시면 좋을 것 같습니다.