-
Notifications
You must be signed in to change notification settings - Fork 169
[Spring JDBC] 강동현 5,6,7 단계 미션 제출합니다. #529
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
base: mintcoke123
Are you sure you want to change the base?
Changes from all commits
a26d3bd
33475a6
2759859
c32009e
7489cf5
7543356
565d8f2
be87cab
e1fcf2b
b1b4fb9
f8655df
d75c0dd
2426350
59d2619
3470311
f385424
0343da9
afb174a
b6d22f2
7931473
46a253d
b92cdfb
70a9b67
102f026
2d7ef51
4e37450
9268065
31af366
1982c76
f59f320
9743e4a
10a094a
5c852cc
9aa4ca9
75bd872
63c9eff
10c8b9f
0b545da
9759c2d
9a5996a
45fcdef
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
This file was deleted.
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,62 @@ | ||
| package roomescape.dao; | ||
|
|
||
| import org.springframework.jdbc.core.JdbcTemplate; | ||
| import org.springframework.jdbc.core.RowMapper; | ||
| import org.springframework.jdbc.core.simple.SimpleJdbcInsert; | ||
| import org.springframework.stereotype.Repository; | ||
| import roomescape.domain.Reservation; | ||
|
|
||
| import java.util.HashMap; | ||
| import java.util.List; | ||
| import java.util.Map; | ||
|
|
||
| @Repository | ||
| public class ReservationDao { | ||
|
|
||
| private final JdbcTemplate jdbcTemplate; | ||
| private final SimpleJdbcInsert simpleInsert; | ||
|
|
||
| public ReservationDao(JdbcTemplate jdbcTemplate) { | ||
| this.jdbcTemplate = jdbcTemplate; | ||
| this.simpleInsert = new SimpleJdbcInsert(jdbcTemplate) | ||
| .withTableName("reservation") | ||
| .usingGeneratedKeyColumns("id"); | ||
| } | ||
|
|
||
| private final RowMapper<Reservation> rowMapper = (resultSet, rowNum) -> | ||
|
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. 👍 |
||
| new Reservation( | ||
| resultSet.getLong("id"), | ||
| resultSet.getString("name"), | ||
| resultSet.getString("date"), | ||
| resultSet.getString("time") | ||
| ); | ||
|
|
||
| public List<Reservation> findAll() { | ||
| return jdbcTemplate.query( | ||
| "SELECT id, name, date, time FROM reservation", | ||
| rowMapper | ||
| ); | ||
| } | ||
|
|
||
| public long insert(String name, String date, String time) { | ||
| Map<String, Object> params = new HashMap<>(); | ||
| params.put("name", name); | ||
| params.put("date", date); | ||
| params.put("time", time); | ||
|
|
||
| Number key = simpleInsert.executeAndReturnKey(params); | ||
| return key.longValue(); | ||
| } | ||
|
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. 현재 insert 메서드에서 KeyHolder와 JDBC 템플릿을 사용하여 데이터 삽입 후 자동 생성된 id를 가져오는 구현 방식을 잘 구현해주신 것 같아요 👍 Simplejdbcinsert라는 객체를 들어보셨을까요? 참고 사항으로 말씀드리자면, 해당 객체를 사용한다면 코드가 좀 더 간결해진다는 장점이 있습니다.
Author
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. 저번 스터디에서 진행했습니다! 코드 길이도 짧아지고 가시성도 좋아지네요. 적용 완료했습니다! |
||
|
|
||
| public Reservation findById(long id) { | ||
| return jdbcTemplate.queryForObject( | ||
| "SELECT id, name, date, time FROM reservation WHERE id = ?", | ||
| rowMapper, | ||
| id | ||
| ); | ||
| } | ||
|
|
||
| public int deleteById(long id) { | ||
| return jdbcTemplate.update("DELETE FROM reservation WHERE id = ?", id); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,7 @@ | ||
| package roomescape.service; | ||
|
|
||
| import org.springframework.stereotype.Component; | ||
| import org.springframework.stereotype.Service; | ||
| import roomescape.dao.ReservationDao; | ||
| import roomescape.dto.ReservationResponse; | ||
| import roomescape.dto.ReservationRequest; | ||
| import roomescape.exception.InvalidReservationRequestException; | ||
|
|
@@ -9,54 +10,54 @@ | |
|
|
||
| import java.util.ArrayList; | ||
| import java.util.List; | ||
| import java.util.Map; | ||
| import java.util.HashMap; | ||
| import java.util.concurrent.atomic.AtomicLong; | ||
| import java.util.logging.Logger; | ||
|
|
||
| @Component | ||
| @Service | ||
| public class ReservationList { | ||
|
|
||
| private final Map<Long, Reservation> idToReservation = new HashMap<>(); | ||
| private AtomicLong index; | ||
| public ReservationList() { | ||
| this.index = new AtomicLong(0); | ||
| private final ReservationDao reservationDao; | ||
| private static final Logger logger = Logger.getLogger(ReservationList.class.getName()); | ||
|
|
||
| public ReservationList(ReservationDao reservationDao) { | ||
| this.reservationDao = reservationDao; | ||
| } | ||
|
|
||
| public List<ReservationResponse> findAll() { | ||
| List<Reservation> results = reservationDao.findAll(); | ||
| List<ReservationResponse> responses = new ArrayList<>(); | ||
| for (Reservation reservation : idToReservation.values()) { | ||
| for (Reservation reservation : results) { | ||
| responses.add(toResponse(reservation)); | ||
| } | ||
| return responses; | ||
| } | ||
|
|
||
| public ReservationResponse create(ReservationRequest request) { | ||
| if (request.name() == null || request.name().isBlank() | ||
| || request.date() == null || request.date().isBlank() | ||
| || request.time() == null || request.time().isBlank()) { | ||
| throw new InvalidReservationRequestException( | ||
| "잘못된 예약 요청입니다. " + | ||
| "name=" + request.name() + | ||
| ", date=" + request.date() + | ||
| ", time=" + request.time() | ||
| ); | ||
| || request.date() == null || request.date().isBlank() | ||
| || request.time() == null || request.time().isBlank()) { | ||
| logger.warning("Invalid request: " + request); | ||
| throw new InvalidReservationRequestException("잘못된 예약 요청입니다."); | ||
| } | ||
|
|
||
| long newId = index.incrementAndGet(); | ||
| Reservation reservation = new Reservation(newId, request.name(), request.date(), request.time()); | ||
| idToReservation.put(newId, reservation); | ||
| return toResponse(reservation); | ||
| long id = reservationDao.insert(request.name(), request.date(), request.time()); | ||
| Reservation saved = reservationDao.findById(id); | ||
| return toResponse(saved); | ||
| } | ||
|
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.
Author
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.
저장 직후 DB에서 방금 저장한 레코드를 다시 조회해 그 값으로 응답을 생성하도록 로직을 변경하였습니다! |
||
|
|
||
| public void delete(long id) { | ||
| if (!idToReservation.containsKey(id)) { | ||
| throw new NotFoundReservationException("해당 분실물을 찾을 수 없습니다: " + id); | ||
| int updated = reservationDao.deleteById(id); | ||
| if (updated == 0) { | ||
| throw new NotFoundReservationException("해당 예약을 찾을 수 없습니다: " + id); | ||
| } | ||
| idToReservation.remove(id); | ||
| } | ||
|
|
||
| private ReservationResponse toResponse(Reservation reservation) { | ||
| return new ReservationResponse(reservation.getId(), reservation.getName(), reservation.getDate(), reservation.getTime()); | ||
| return new ReservationResponse( | ||
| reservation.getId(), | ||
| reservation.getName(), | ||
| reservation.getDate(), | ||
| reservation.getTime() | ||
| ); | ||
| } | ||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| spring.h2.console.enabled=true | ||
| spring.h2.console.path=/h2-console | ||
|
|
||
| spring.datasource.url=jdbc:h2:mem:database | ||
| spring.datasource.driver-class-name=org.h2.Driver |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| CREATE TABLE reservation | ||
| ( | ||
| id BIGINT NOT NULL AUTO_INCREMENT, | ||
| name VARCHAR(255) NOT NULL, | ||
| date VARCHAR(255) NOT NULL, | ||
| time VARCHAR(255) NOT NULL, | ||
| PRIMARY KEY (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.
동현님이 생각하시는 DAO와 Repository의 차이는 무엇인가요?
또한 DAO로 이름 지으신 후
@Repository어노테이션을 사용하셨는데 이유가 궁금합니다!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.
dao는 service레이어 이전에 데이터베이스와 직접 상호작용하는 계층으로, 순수한 데이터 접근 로직을 담당합니다.
Repository는 도메인 컬렉션처럼 동작하는 추상화라고 하는군요! 처음 알았습니다.
dao의 어노테이션을
Repository라고 지은 이유는, dao 계층을 표현할 때에는@Repository어노테이션을 사용한다는 레퍼런스를 참고했기 때문입니다.https://whitekeyboard.tistory.com/178
찾아보니
@Repository어노테이션은 JDBC 에서 발생하는 SQLException 같은 걸 스프링이 DataAccessException 계열 예외로 변환해 주는 역할을 수행한다고 하네요