-
Notifications
You must be signed in to change notification settings - Fork 170
[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?
Conversation
SANGHEEJEONG
left a comment
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.
안녕하세요, 동현님 오랜만입니다!
이번 미션도 파이팅 해봐요 🏃♂️🙌
| import java.util.List; | ||
|
|
||
| @Repository | ||
| public class ReservationDao { |
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 계열 예외로 변환해 주는 역할을 수행한다고 하네요
| this.jdbcTemplate = jdbcTemplate; | ||
| } | ||
|
|
||
| private final RowMapper<Reservation> rowMapper = (resultSet, rowNum) -> |
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.
👍
| return ps; | ||
| }, keyHolder); | ||
| return keyHolder.getKey().longValue(); | ||
| } |
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.
현재 insert 메서드에서 KeyHolder와 JDBC 템플릿을 사용하여 데이터 삽입 후 자동 생성된 id를 가져오는 구현 방식을 잘 구현해주신 것 같아요 👍
Simplejdbcinsert라는 객체를 들어보셨을까요? 참고 사항으로 말씀드리자면, 해당 객체를 사용한다면 코드가 좀 더 간결해진다는 장점이 있습니다.
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.
저번 스터디에서 진행했습니다! 코드 길이도 짧아지고 가시성도 좋아지네요. 적용 완료했습니다!
| import java.util.HashMap; | ||
| import java.util.concurrent.atomic.AtomicLong; | ||
|
|
||
| @Component |
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.
@Service가 아닌 @Component를 붙인 이유가 궁금합니다!
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.
레이어는 @component어노테이션으로 싱글톤으로 만들어야 하기 때문에, @component를 사용하였고 레이어마다 어노테이션이 다른 것을 중간에 알았지만 수정을 못했습니다. 수정했습니다!
| return toResponse(reservation); | ||
| long id = reservationDao.insert(request.name(), request.date(), request.time()); | ||
| return new ReservationResponse(id, request.name(), request.date(), request.time()); | ||
| } |
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.
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.
- 응답 dto를 사용한 이유는, dto로 도메인 모델과 API 응답 모델을 분리해 변경에 대한 영향도를 줄이는 것이 이후 리팩토링에 더욱 효과적이라고 생각했기 때문입니다.
- 지금 코드에서는 말씀주신대로 dto 생성 시 서비스에서 request 값으로 바로 Response를 만들고 있었기 때문에 db의 기본값이 달라지면(ex: string 트리밍 등) 실제 저장된 값과 응답이 달라질 수 있다는 것을 알게 되었습니다!
저장 직후 DB에서 방금 저장한 레코드를 다시 조회해 그 값으로 응답을 생성하도록 로직을 변경하였습니다!
수정했습니다!
| throw new InvalidReservationRequestException( | ||
| "잘못된 예약 요청입니다. " + | ||
| "name=" + request.name() + | ||
| ", date=" + request.date() + | ||
| ", time=" + request.time() | ||
| "name=" + request.name() + | ||
| ", date=" + request.date() + | ||
| ", time=" + request.time() | ||
| ); |
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.
지금 코드에서는 예외 메시지에 name, date, time 같은 요청값을 그대로 넣고 있는데요. 개발 환경에서는 큰 문제가 없지만 운영 환경에서는 사용자 입력값이 그대로 노출되는 문제가 발생할 수 있어서 보통 로그에는 실제 요청값을 남기고, 사용자에게는 간단한 메시지만 전달하는 방식을 사용하는 편입니다!
<로그>
logger.warning("Invalid request: " + request)<예외 메시지>
throw new InvalidReservationRequestException("잘못된 예약 요청입니다.")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.
logger를 사용하는 게 캡슐화에도 더 좋아보이네요!
해당 방식으로 수정했습니다!
SANGHEEJEONG
left a comment
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.
리뷰 잘 반영해주셨네요!! 짱 🙌
다음 미션도 진행하셔야 하니, 이정도로 마무리해도 좋을 것 같습니다.
수고하셨습니다 ~

안녕하세요! 정상희 리뷰어님!
스프링 미션 5,6,7 제출하겠습니다~!
이번 미션도 잘부탁드립니다!
🚀 미션 내용
이번 5,6,7단계 미션은 db와의 연결과 상호작용을 다루는 내용이었습니다.
📊 구현 순서
▶5단계
▶6단계
▶7단계
delete(): DELETE ... 실행; 영향 0이면 NotFoundReservationException(404)