-
Notifications
You must be signed in to change notification settings - Fork 97
[우아한명지코스] 고건 Spring Data JPA 4, 5, 6단계 미션 제출합니다. #227
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: gopistol
Are you sure you want to change the base?
Changes from all commits
2023c4a
0f5fa37
890636a
85b5bb6
f77d137
58ee57e
0e4d417
4daba68
48d6333
fa0fde5
b02bff5
0de947d
4073929
19c3ee8
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 |
|---|---|---|
| @@ -1,74 +1,74 @@ | ||
| package roomescape.member; | ||
|
|
||
| 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.member.domain.Member; | ||
| import roomescape.member.domain.Role; | ||
|
|
||
| @Repository | ||
| public class MemberDao { | ||
|
|
||
| private JdbcTemplate jdbcTemplate; | ||
|
|
||
| public MemberDao(JdbcTemplate jdbcTemplate) { | ||
| this.jdbcTemplate = jdbcTemplate; | ||
| } | ||
|
|
||
| public Member save(Member member) { | ||
| KeyHolder keyHolder = new GeneratedKeyHolder(); | ||
| jdbcTemplate.update(connection -> { | ||
| var ps = connection.prepareStatement( | ||
| "INSERT INTO member(name, email, password, role) VALUES (?, ?, ?, ?)", | ||
| new String[]{"id"}); | ||
| ps.setString(1, member.getName()); | ||
| ps.setString(2, member.getEmail()); | ||
| ps.setString(3, member.getPassword()); | ||
| ps.setString(4, member.getRole().name()); | ||
| return ps; | ||
| }, keyHolder); | ||
|
|
||
| return new Member(keyHolder.getKey().longValue(), member.getName(), member.getEmail(), | ||
| Role.USER); | ||
| } | ||
|
|
||
| public Member findByEmailAndPassword(String email, String password) { | ||
| return jdbcTemplate.queryForObject( | ||
| "SELECT id, name, email, role FROM member WHERE email = ? AND password = ?", | ||
| (rs, rowNum) -> new Member( | ||
| rs.getLong("id"), | ||
| rs.getString("name"), | ||
| rs.getString("email"), | ||
| Role.valueOf(rs.getString("role")) | ||
| ), | ||
| email, password | ||
| ); | ||
| } | ||
|
|
||
| public Member findByName(String name) { | ||
| return jdbcTemplate.queryForObject( | ||
| "SELECT id, name, email, role FROM member WHERE name = ?", | ||
| (rs, rowNum) -> new Member( | ||
| rs.getLong("id"), | ||
| rs.getString("name"), | ||
| rs.getString("email"), | ||
| Role.valueOf(rs.getString("role")) | ||
| ), | ||
| name | ||
| ); | ||
| } | ||
|
|
||
| public Member findById(Long id) { | ||
| return jdbcTemplate.queryForObject( | ||
| "SELECT id, name, email, role FROM member WHERE id = ?", | ||
| (rs, rowNum) -> new Member( | ||
| rs.getLong("id"), | ||
| rs.getString("name"), | ||
| rs.getString("email"), | ||
| Role.valueOf(rs.getString("role")) | ||
| ), | ||
| id | ||
| ); | ||
| } | ||
| } | ||
| //package roomescape.member; | ||
|
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. 혹시 추후에 다시 사용하는 코드인가요?? 주석을 달아서 의도를 표현해도 좋을 것 같고, 그런게 아니라면 삭제하는것도 좋아보입니다. |
||
| // | ||
| //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.member.domain.Member; | ||
| //import roomescape.member.domain.Role; | ||
| // | ||
| //@Repository | ||
| //public class MemberDao { | ||
| // | ||
| // private JdbcTemplate jdbcTemplate; | ||
| // | ||
| // public MemberDao(JdbcTemplate jdbcTemplate) { | ||
| // this.jdbcTemplate = jdbcTemplate; | ||
| // } | ||
| // | ||
| // public Member save(Member member) { | ||
| // KeyHolder keyHolder = new GeneratedKeyHolder(); | ||
| // jdbcTemplate.update(connection -> { | ||
| // var ps = connection.prepareStatement( | ||
| // "INSERT INTO member(name, email, password, role) VALUES (?, ?, ?, ?)", | ||
| // new String[]{"id"}); | ||
| // ps.setString(1, member.getName()); | ||
| // ps.setString(2, member.getEmail()); | ||
| // ps.setString(3, member.getPassword()); | ||
| // ps.setString(4, member.getRole().name()); | ||
| // return ps; | ||
| // }, keyHolder); | ||
| // | ||
| // return new Member(keyHolder.getKey().longValue(), member.getName(), member.getEmail(), | ||
| // Role.USER); | ||
| // } | ||
| // | ||
| // public Member findByEmailAndPassword(String email, String password) { | ||
| // return jdbcTemplate.queryForObject( | ||
| // "SELECT id, name, email, role FROM member WHERE email = ? AND password = ?", | ||
| // (rs, rowNum) -> new Member( | ||
| // rs.getLong("id"), | ||
| // rs.getString("name"), | ||
| // rs.getString("email"), | ||
| // Role.valueOf(rs.getString("role")) | ||
| // ), | ||
| // email, password | ||
| // ); | ||
| // } | ||
| // | ||
| // public Member findByName(String name) { | ||
| // return jdbcTemplate.queryForObject( | ||
| // "SELECT id, name, email, role FROM member WHERE name = ?", | ||
| // (rs, rowNum) -> new Member( | ||
| // rs.getLong("id"), | ||
| // rs.getString("name"), | ||
| // rs.getString("email"), | ||
| // Role.valueOf(rs.getString("role")) | ||
| // ), | ||
| // name | ||
| // ); | ||
| // } | ||
| // | ||
| // public Member findById(Long id) { | ||
| // return jdbcTemplate.queryForObject( | ||
| // "SELECT id, name, email, role FROM member WHERE id = ?", | ||
| // (rs, rowNum) -> new Member( | ||
| // rs.getLong("id"), | ||
| // rs.getString("name"), | ||
| // rs.getString("email"), | ||
| // Role.valueOf(rs.getString("role")) | ||
| // ), | ||
| // id | ||
| // ); | ||
| // } | ||
| //} | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,38 +1,46 @@ | ||
| package roomescape.member; | ||
|
|
||
| import java.util.Optional; | ||
| import org.springframework.stereotype.Service; | ||
| import roomescape.auth.dto.LoginRequest; | ||
| import roomescape.member.domain.Member; | ||
| import roomescape.member.domain.Role; | ||
| import roomescape.member.dto.MemberAuthInfo; | ||
| import roomescape.member.dto.MemberRequest; | ||
| import roomescape.member.dto.MemberResponse; | ||
| import roomescape.member.repository.MemberRepository; | ||
|
|
||
| @Service | ||
| public class MemberService { | ||
|
|
||
| private MemberDao memberDao; | ||
| private MemberRepository memberRepository; | ||
|
|
||
| public MemberService(MemberDao memberDao) { | ||
| this.memberDao = memberDao; | ||
| public MemberService(MemberRepository memberRepository) { | ||
| this.memberRepository = memberRepository; | ||
| } | ||
|
|
||
| public MemberResponse createMember(MemberRequest memberRequest) { | ||
| Member member = memberDao.save(new Member(memberRequest.name(), memberRequest.email(), | ||
| memberRequest.password(), Role.USER)); | ||
| Member member = memberRepository.save( | ||
| new Member(memberRequest.name(), memberRequest.email(), | ||
| memberRequest.password(), Role.USER)); | ||
| return new MemberResponse(member.getId(), member.getName(), member.getEmail()); | ||
| } | ||
|
|
||
| public Member getMemberWithLoginRequest(LoginRequest loginRequest) { | ||
| return memberDao.findByEmailAndPassword( | ||
| public MemberAuthInfo getMemberWithLoginRequest(LoginRequest loginRequest) { | ||
| Optional<Member> memberOptional = memberRepository.findByEmailAndPassword( | ||
| loginRequest.email(), | ||
| loginRequest.password()); | ||
| } | ||
| Member member = memberOptional.orElseThrow(); | ||
|
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. 예외에 대한 내용이 안 적혀있네요. 이 경우에는 어떤 예외가 던져지나요?? |
||
|
|
||
| return new MemberAuthInfo( | ||
|
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. 취향차이긴한데, MemberAuthInfo에서 정적 팩토리 메서드를 하나 만들어서 생성하는것도 좋아보이네요. 이 부분은 참고만 해주세요! |
||
| member.getId(), | ||
| member.getName(), | ||
| member.getRole().name() | ||
| ); | ||
|
|
||
| public Member findById(Long id) { | ||
| return memberDao.findById(id); | ||
| } | ||
|
|
||
| public Member findByName(String name) { | ||
| return memberDao.findByName(name); | ||
| public Optional<Member> findByName(String name) { | ||
| return memberRepository.findByName(name); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,13 +1,35 @@ | ||
| package roomescape.member.domain; | ||
|
|
||
| import jakarta.persistence.Entity; | ||
| import jakarta.persistence.EnumType; | ||
| import jakarta.persistence.Enumerated; | ||
| import jakarta.persistence.GeneratedValue; | ||
| import jakarta.persistence.GenerationType; | ||
| import jakarta.persistence.Id; | ||
| import jakarta.persistence.OneToMany; | ||
| import java.util.HashSet; | ||
| import java.util.Set; | ||
| import roomescape.reservation.domain.Reservation; | ||
|
|
||
| @Entity | ||
| public class Member { | ||
|
|
||
| @Id | ||
| @GeneratedValue(strategy = GenerationType.IDENTITY) | ||
|
Comment on lines
+17
to
+18
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. @GenerateValue 전략에는 어떤게 있나요? IDENTITY를 선택한 이유가 있나요?? |
||
| private Long id; | ||
|
|
||
| private String name; | ||
|
|
||
| private String email; | ||
|
|
||
| private String password; | ||
|
|
||
| @Enumerated(EnumType.STRING) | ||
| private Role role; | ||
|
|
||
| @OneToMany(mappedBy = "member") | ||
| private Set<Reservation> reservations = new HashSet<>(); | ||
|
|
||
| public Member(Long id, String name, String email, Role role) { | ||
|
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. 이 생성자는 어디에 필요한거에요?? |
||
| this.id = id; | ||
| this.name = name; | ||
|
|
@@ -22,6 +44,10 @@ public Member(String name, String email, String password, Role role) { | |
| this.role = role; | ||
| } | ||
|
|
||
| public Member() { | ||
|
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인 이유가 있을까요? protected 혹은 private은 불가능한가요?? private이 불가능하다면 왜 불가능할까요?? |
||
|
|
||
| } | ||
|
|
||
| public Long getId() { | ||
| return id; | ||
| } | ||
|
|
@@ -41,4 +67,8 @@ public String getPassword() { | |
| public Role getRole() { | ||
| return role; | ||
| } | ||
|
|
||
| public Set<Reservation> getReservations() { | ||
| return reservations; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| package roomescape.member.dto; | ||
|
|
||
| public record MemberAuthInfo(Long memberId, String name, String stringRole) { | ||
|
|
||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| package roomescape.member.repository; | ||
|
|
||
| import java.util.Optional; | ||
| import org.springframework.data.jpa.repository.JpaRepository; | ||
| import roomescape.member.domain.Member; | ||
|
|
||
| public interface MemberRepository extends JpaRepository<Member, Long> { | ||
|
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 대신에 Repository를 쓴 이유가 있을까요? 어떤 차이점을 느껴서 Repository로 네이밍을 변경하신거에요?? |
||
|
|
||
| Optional<Member> findByName(String name); | ||
|
|
||
| Optional<Member> findByEmailAndPassword(String email, String password); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -15,8 +15,11 @@ | |
| import roomescape.member.domain.Member; | ||
| import roomescape.member.domain.Role; | ||
| import roomescape.member.MemberService; | ||
| import roomescape.reservation.dto.MyReservationResponse; | ||
| import roomescape.reservation.dto.ReservationRequest; | ||
| import roomescape.reservation.dto.ReservationResponse; | ||
| import roomescape.reservation.dto.WaitingRequest; | ||
| import roomescape.reservation.dto.WaitingResponse; | ||
|
|
||
| @RestController | ||
| public class ReservationController { | ||
|
|
@@ -35,6 +38,11 @@ public List<ReservationResponse> list() { | |
| return reservationService.findAll(); | ||
| } | ||
|
|
||
| @GetMapping("/reservations-mine") | ||
| public List<MyReservationResponse> getMyReservations(@LoginMember Member member) { | ||
| return reservationService.findByMember(member); | ||
| } | ||
|
|
||
| @PostMapping("/reservations") | ||
| public ResponseEntity create(@RequestBody @Valid ReservationRequest reservationRequest, | ||
| @LoginMember Member loginMember) { | ||
|
|
@@ -45,10 +53,24 @@ public ResponseEntity create(@RequestBody @Valid ReservationRequest reservationR | |
| .body(reservation); | ||
| } | ||
|
|
||
|
|
||
| @DeleteMapping("/reservations/{id}") | ||
| public ResponseEntity delete(@PathVariable Long id) { | ||
| reservationService.deleteById(id); | ||
| public ResponseEntity delete(@PathVariable Long id, @LoginMember Member member) { | ||
| reservationService.deleteById(id, member); | ||
| return ResponseEntity.noContent().build(); | ||
| } | ||
|
|
||
| @PostMapping("/waitings") | ||
| public ResponseEntity createWaiting(@RequestBody @Valid WaitingRequest waitingRequest, | ||
| @LoginMember Member loginMember) { | ||
| WaitingResponse waiting = reservationService.saveWaiting(waitingRequest, loginMember); | ||
|
|
||
| return ResponseEntity.created(URI.create("/reservations/" + waiting.id())) | ||
| .body(waiting); | ||
| } | ||
|
|
||
| @DeleteMapping("/waitings/cancel/{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. 어차피 HTTP Method가 delete인데, cancel이라는 꾸밈어가 필요한가요?? |
||
| public ResponseEntity cancelWaiting(@PathVariable Long id, @LoginMember Member member) { | ||
| reservationService.deleteWaitingById(id, member); | ||
| return ResponseEntity.noContent().build(); | ||
| } | ||
|
|
||
|
|
@@ -57,7 +79,7 @@ private Member resolveReservationMember(ReservationRequest reservationRequest, | |
| Member member; | ||
|
|
||
| if (loginMember.getRole() == Role.ADMIN && reservationRequest.name() != null) { | ||
| member = memberService.findByName(reservationRequest.name()); | ||
| member = memberService.findByName(reservationRequest.name()).orElseThrow(); | ||
|
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. 기존에 있던 코드 같긴 한데, 별도의 Interceptor + ArgumentResolver를 사용하면, 더 응집도있게 권한 검증을 할 수 있을 것 같아요. |
||
| return member; | ||
| } | ||
| return loginMember; | ||
|
|
||
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.
쿠키에 관한 세부 로직은 별도의 객체에서 관리해도 좋을 것 같아요.