diff --git a/build.gradle b/build.gradle index 8d52aebc6..69211f7fb 100644 --- a/build.gradle +++ b/build.gradle @@ -15,7 +15,7 @@ repositories { dependencies { implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' - implementation 'org.springframework.boot:spring-boot-starter-jdbc' + implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'dev.akkinoc.spring.boot:logback-access-spring-boot-starter:4.0.0' @@ -27,6 +27,12 @@ dependencies { testImplementation 'io.rest-assured:rest-assured:5.3.1' runtimeOnly 'com.h2database:h2' + + compileOnly 'org.projectlombok:lombok' + annotationProcessor 'org.projectlombok:lombok' + + testCompileOnly 'org.projectlombok:lombok' + testAnnotationProcessor 'org.projectlombok:lombok' } test { diff --git a/src/main/README.md b/src/main/README.md index 086ab29ab..7b9db330f 100644 --- a/src/main/README.md +++ b/src/main/README.md @@ -2,28 +2,26 @@ 안녕하세요. 세종대학교 그리디 백엔드 4기 이채현입니다. +이번주는 꽤나 여유로워서 많은 시간을 투자할 수 있을 것 같아요! 많은 피드백 부탁드립니다.!!! + --- -## Spring MVC 미션 3단계 - 관리자 기능 +## Spring JPA 4-6단계 Entity Manager-> JPA + +entity매니저를 사용해서 repository 수정 +jpa 전환 및 내 예약 구성코드를 생성함. -어드민 페이지 진입은 admin 권한이 있는 사람만 할 수 있도록 제한한다. -만약 진입 권한이 없다면 401 코드를 응답하도록 한다. --- ### 고민한 내용 🤔 +EntityManager를 JPA로 바꾸려면 어떠한 형식을 가져야 하는가 고민했습니다. -- HandlerInterceptor에서 기본적으로 preHandle/postHandle/afterCompletion으로 나뉘어져있던데, -이번의 경우에는 admin페이지 접속만을 확인하면 되는거라서 preHandle만을 사용했습니다. -이경우에는 postHandle과 afterCompletion을 어떻게 구성하면 좋을지..? 알고 싶네요. - - -- WebConfig 같은 경우에는, admin 페이지를 접속할때의 role만을 확인해주면 되므로 /admin/***을 사용해주었습니다. +사용해보니, JPA가 EntityManager보다 더 적은 메서드를 쓰고도 충분히 구현되는 것 같습니다.! -- token 만료시간도 있어야할 것 같아서 expire_time을 이용해서,만료시간을 구현해보았습니다. 만료시간을 구현할 더 좋은 -방법이 있을지?? 궁금합니다. +실무에서는 JPA를 더 많이 사용하게 될 것 같은데, EntityManager를 사용하게 되는 경우도 있나요? -- token을 accessToken과 refreshToken으로 나눠서 구현해주었는데, 구현하다보니 너무 어려워서 제대로 구현된건지 잘 -모르겠습니다. +그리고 Entity에서 단순히 protected를 추가한 것 만으로, 테스트가 돌아가는 경우가 있는데 +이 protected의 의미를 잘 모르겠습니다. diff --git a/src/main/java/roomescape/CookieManager.java b/src/main/java/roomescape/CookieManager.java index 22b74fea8..37966006a 100644 --- a/src/main/java/roomescape/CookieManager.java +++ b/src/main/java/roomescape/CookieManager.java @@ -1,13 +1,13 @@ package roomescape; import jakarta.servlet.http.Cookie; +import org.springframework.stereotype.Component; import roomescape.exception.TokenNotFoundException; import java.util.Arrays; +@Component public class CookieManager { - - public String extractToken(Cookie[] cookies, String cookieName) { return Arrays.stream(cookies) .filter(cookie -> cookieName.equals(cookie.getName())) diff --git a/src/main/java/roomescape/login/LoginController.java b/src/main/java/roomescape/login/LoginController.java index f3e46d0e7..d8770b0f8 100644 --- a/src/main/java/roomescape/login/LoginController.java +++ b/src/main/java/roomescape/login/LoginController.java @@ -71,7 +71,7 @@ public ResponseEntity refresh(HttpServletRequest request, HttpServletRespo @GetMapping("/login/check") public ResponseEntity checkLogin(LoginMember loginMember) { - Long memberId = loginMember.id(); + Long memberId = loginMember.getId(); MemberResponse memberResponse = loginService.checkLogin(memberId); return ResponseEntity.ok(memberResponse); } diff --git a/src/main/java/roomescape/login/LoginInterceptor.java b/src/main/java/roomescape/login/LoginInterceptor.java index 0c431b54c..479d447fd 100644 --- a/src/main/java/roomescape/login/LoginInterceptor.java +++ b/src/main/java/roomescape/login/LoginInterceptor.java @@ -8,32 +8,41 @@ import roomescape.CookieManager; import roomescape.JwtProvider; import roomescape.member.Member; -import roomescape.member.MemberDao; +import roomescape.member.MemberRepository; @Component public class LoginInterceptor implements HandlerInterceptor { private final JwtProvider jwtProvider; - private final MemberDao memberDao; + private final MemberRepository memberRepository; private final CookieManager cookieManager; - public LoginInterceptor(JwtProvider jwtProvider, MemberDao memberDao, CookieManager cookieManager) { + public LoginInterceptor(JwtProvider jwtProvider, MemberRepository memberRepository, CookieManager cookieManager) { this.jwtProvider = jwtProvider; - this.memberDao = memberDao; + this.memberRepository = memberRepository; this.cookieManager = cookieManager; } @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { - Cookie[] cookies = request.getCookies(); + Cookie[] cookies = getCookies(request); - String token = cookieManager.extractToken(cookies, "accessToken"); + String token = cookieManager.extractToken(cookies,"accessToken"); Long memberId = jwtProvider.getMemberId(token); - Member member = memberDao.findById(memberId); - if (member == null || !member.getRole().equals("ADMIN")) { + Member member = memberRepository.findById(memberId) + .orElseThrow(); + if (!member.getRole().equals("ADMIN")) { response.setStatus(401); return false; } return true; } + + private Cookie[] getCookies(HttpServletRequest httpServletRequest) { + Cookie[] cookies = httpServletRequest.getCookies(); + if (cookies == null) { + throw new IllegalStateException("cookie is not exist"); + } + return cookies; + } } diff --git a/src/main/java/roomescape/login/LoginMember.java b/src/main/java/roomescape/login/LoginMember.java index 63b947ac9..58c102752 100644 --- a/src/main/java/roomescape/login/LoginMember.java +++ b/src/main/java/roomescape/login/LoginMember.java @@ -1,9 +1,22 @@ package roomescape.login; -public record LoginMember( - Long id, - String name, - String email, - String role -) { +import lombok.Getter; + + +@Getter +public class LoginMember { + private final Long id; + private final String name; + private final String email; + private final String password; + private final String role; + + public LoginMember(Long id, String name, String email, String password, String role) { + this.id = id; + this.name = name; + this.email = email; + this.password = password; + this.role = role; + } + } diff --git a/src/main/java/roomescape/login/LoginMemberArgumentResolver.java b/src/main/java/roomescape/login/LoginMemberArgumentResolver.java index 5d4909850..4c3e9c31f 100644 --- a/src/main/java/roomescape/login/LoginMemberArgumentResolver.java +++ b/src/main/java/roomescape/login/LoginMemberArgumentResolver.java @@ -11,15 +11,15 @@ import roomescape.CookieManager; import roomescape.JwtProvider; import roomescape.member.Member; -import roomescape.member.MemberDao; +import roomescape.member.MemberRepository; @Component public class LoginMemberArgumentResolver implements HandlerMethodArgumentResolver { - private final MemberDao memberDao; + private final MemberRepository memberRepository; private final JwtProvider jwtProvider; private final CookieManager cookieManager; - public LoginMemberArgumentResolver(JwtProvider jwtProvider, MemberDao memberDao,CookieManager cookieManager) { - this.memberDao = memberDao; + public LoginMemberArgumentResolver(JwtProvider jwtProvider, MemberRepository memberRepository,CookieManager cookieManager) { + this.memberRepository = memberRepository; this.jwtProvider = jwtProvider; this.cookieManager=cookieManager; } @@ -38,9 +38,10 @@ public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer m Long memberId = jwtProvider.getMemberId(token); - Member member = memberDao.findById(memberId); + Member member = memberRepository.findById(memberId) + .orElseThrow(); - return new LoginMember(member.getId(), member.getName(), member.getEmail(), member.getRole()); + return new LoginMember(memberId, member.getName(), member.getEmail(), member.getPassword(),member.getRole()); } private HttpServletRequest getRequest(NativeWebRequest nativeWebRequest) { @@ -58,5 +59,4 @@ private Cookie[] getCookies(HttpServletRequest httpServletRequest) { } return cookies; } - } diff --git a/src/main/java/roomescape/login/LoginService.java b/src/main/java/roomescape/login/LoginService.java index 6085212f4..90343fa09 100644 --- a/src/main/java/roomescape/login/LoginService.java +++ b/src/main/java/roomescape/login/LoginService.java @@ -2,36 +2,34 @@ import org.springframework.stereotype.Service; import roomescape.member.Member; -import roomescape.member.MemberDao; +import roomescape.member.MemberRepository; import roomescape.member.MemberResponse; @Service public class LoginService { - private final MemberDao memberDao; + private final MemberRepository memberRepository; - public LoginService(MemberDao memberDao) { - this.memberDao = memberDao; + public LoginService(MemberRepository memberRepository) { + this.memberRepository = memberRepository; } public Member login(String email, String password) { - Member member = memberDao.findByEmailAndPassword(email, password); - if (member == null) { - throw new RuntimeException("Invalid email or password"); - } + Member member = memberRepository.findByEmailAndPassword(email, password) + .orElseThrow(); + return member; } public MemberResponse checkLogin(Long memberId) { - Member member = memberDao.findById(memberId); - if (member == null) { - throw new RuntimeException("Invalid email or password"); - } + Member member = memberRepository.findById(memberId) + .orElseThrow(); return new MemberResponse(member.getId(), member.getName(), member.getEmail()); } public Member findById(Long id) { - Member member = memberDao.findById(id); + Member member = memberRepository.findById(id) + .orElseThrow(); return member; } diff --git a/src/main/java/roomescape/member/Member.java b/src/main/java/roomescape/member/Member.java index 903aaa9b0..44387d634 100644 --- a/src/main/java/roomescape/member/Member.java +++ b/src/main/java/roomescape/member/Member.java @@ -1,43 +1,36 @@ package roomescape.member; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Entity +@Getter public class Member { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; + private String name; + + @Column(unique = true) private String email; + private String password; private String role; - public Member(Long id, String name, String email, String role) { - this.id = id; - this.name = name; - this.email = email; - this.role = role; - } - + @Builder public Member(String name, String email, String password, String role) { this.name = name; this.email = email; this.password = password; this.role = role; } - - public Long getId() { - return id; - } - - public String getName() { - return name; - } - - public String getEmail() { - return email; - } - - public String getPassword() { - return password; - } - - public String getRole() { - return role; - } } diff --git a/src/main/java/roomescape/member/MemberController.java b/src/main/java/roomescape/member/MemberController.java index fe009d062..513923746 100644 --- a/src/main/java/roomescape/member/MemberController.java +++ b/src/main/java/roomescape/member/MemberController.java @@ -11,7 +11,7 @@ @RestController public class MemberController { - private MemberService memberService; + private final MemberService memberService; public MemberController(MemberService memberService) { this.memberService = memberService; @@ -20,7 +20,7 @@ public MemberController(MemberService memberService) { @PostMapping("/members") public ResponseEntity createMember(@RequestBody MemberRequest memberRequest) { MemberResponse member = memberService.createMember(memberRequest); - return ResponseEntity.created(URI.create("/members/" + member.getId())).body(member); + return ResponseEntity.created(URI.create("/members/" + member.id())).body(member); } @PostMapping("/logout") diff --git a/src/main/java/roomescape/member/MemberDao.java b/src/main/java/roomescape/member/MemberDao.java deleted file mode 100644 index db0b9c68c..000000000 --- a/src/main/java/roomescape/member/MemberDao.java +++ /dev/null @@ -1,68 +0,0 @@ -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; - -@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()); - return ps; - }, keyHolder); - - return new Member(keyHolder.getKey().longValue(), member.getName(), member.getEmail(), "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"), - 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"), - 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"), - rs.getString("role") - ), - id - ); - } -} diff --git a/src/main/java/roomescape/member/MemberRepository.java b/src/main/java/roomescape/member/MemberRepository.java new file mode 100644 index 000000000..01322100c --- /dev/null +++ b/src/main/java/roomescape/member/MemberRepository.java @@ -0,0 +1,14 @@ +package roomescape.member; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.Optional; + +@Repository +public interface MemberRepository extends JpaRepository { + + Optional findByEmailAndPassword(String email, String password); + + Optional findByName(String name); +} diff --git a/src/main/java/roomescape/member/MemberRequest.java b/src/main/java/roomescape/member/MemberRequest.java index cafb79f14..d32583825 100644 --- a/src/main/java/roomescape/member/MemberRequest.java +++ b/src/main/java/roomescape/member/MemberRequest.java @@ -1,19 +1,8 @@ package roomescape.member; -public class MemberRequest { - private String name; - private String email; - private String password; - - public String getName() { - return name; - } - - public String getEmail() { - return email; - } - - public String getPassword() { - return password; - } +public record MemberRequest( + String name, + String email, + String password +) { } diff --git a/src/main/java/roomescape/member/MemberResponse.java b/src/main/java/roomescape/member/MemberResponse.java index b9fa3b97a..f2408ba3e 100644 --- a/src/main/java/roomescape/member/MemberResponse.java +++ b/src/main/java/roomescape/member/MemberResponse.java @@ -1,25 +1,8 @@ package roomescape.member; -public class MemberResponse { - private Long id; - private String name; - private String email; - - public MemberResponse(Long id, String name, String email) { - this.id = id; - this.name = name; - this.email = email; - } - - public Long getId() { - return id; - } - - public String getName() { - return name; - } - - public String getEmail() { - return email; - } +public record MemberResponse( + Long id, + String name, + String email +) { } diff --git a/src/main/java/roomescape/member/MemberService.java b/src/main/java/roomescape/member/MemberService.java index ccaa8cba5..6109bfce7 100644 --- a/src/main/java/roomescape/member/MemberService.java +++ b/src/main/java/roomescape/member/MemberService.java @@ -4,14 +4,20 @@ @Service public class MemberService { - private MemberDao memberDao; + private final 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.getName(), memberRequest.getEmail(), memberRequest.getPassword(), "USER")); + Member member = Member.builder() + .name(memberRequest.name()) + .email(memberRequest.email()) + .password(memberRequest.password()) + .role("USER") + .build(); + memberRepository.save(member); return new MemberResponse(member.getId(), member.getName(), member.getEmail()); } } diff --git a/src/main/java/roomescape/reservation/Reservation.java b/src/main/java/roomescape/reservation/Reservation.java index 83a7edf1b..7b61680af 100644 --- a/src/main/java/roomescape/reservation/Reservation.java +++ b/src/main/java/roomescape/reservation/Reservation.java @@ -1,51 +1,45 @@ package roomescape.reservation; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import roomescape.member.Member; import roomescape.theme.Theme; import roomescape.time.Time; +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Entity +@Getter public class Reservation { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; private String date; + + @ManyToOne + @JoinColumn(name = "member_id") + private Member member; + + @ManyToOne + @JoinColumn(name = "time_id") private Time time; + @ManyToOne + @JoinColumn(name = "theme_id") private Theme theme; - public Reservation(Long id, String name, String date, Time time, Theme theme) { - this.id = id; - this.name = name; - this.date = date; - this.time = time; - this.theme = theme; - } - - public Reservation(String name, String date, Time time, Theme theme) { - this.name = name; + @Builder + public Reservation(Member member, String date, Time time, Theme theme) { + this.member = member; this.date = date; this.time = time; this.theme = theme; } - - public Reservation() { - - } - - public Long getId() { - return id; - } - - public String getName() { - return name; - } - - public String getDate() { - return date; - } - - public Time getTime() { - return time; - } - - public Theme getTheme() { - return theme; - } } diff --git a/src/main/java/roomescape/reservation/ReservationController.java b/src/main/java/roomescape/reservation/ReservationController.java index 95de7ccb5..b8942072f 100644 --- a/src/main/java/roomescape/reservation/ReservationController.java +++ b/src/main/java/roomescape/reservation/ReservationController.java @@ -8,6 +8,7 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; import roomescape.login.LoginMember; +import roomescape.reservation.dto.MyReservationResponse; import java.net.URI; import java.util.List; @@ -29,14 +30,14 @@ public List list() { @PostMapping("/reservations") public ResponseEntity create(@RequestBody ReservationRequest reservationRequest, LoginMember loginMember) { if ( - reservationRequest.getDate() == null - || reservationRequest.getTheme() == null - || reservationRequest.getTime() == null) { + reservationRequest.date() == null + || reservationRequest.theme() == null + || reservationRequest.time() == null) { return ResponseEntity.badRequest().build(); } ReservationResponse reservation = reservationService.save(reservationRequest, loginMember); - return ResponseEntity.created(URI.create("/reservations/" + reservation.getId())).body(reservation); + return ResponseEntity.created(URI.create("/reservations/" + reservation.id())).body(reservation); } @DeleteMapping("/reservations/{id}") @@ -44,4 +45,9 @@ public ResponseEntity delete(@PathVariable Long id) { reservationService.deleteById(id); return ResponseEntity.noContent().build(); } + + @GetMapping("/reservations-mine") + public List reservationMine(LoginMember member) { + return reservationService.findMyReservations(member); + } } diff --git a/src/main/java/roomescape/reservation/ReservationDao.java b/src/main/java/roomescape/reservation/ReservationDao.java deleted file mode 100644 index b029b348c..000000000 --- a/src/main/java/roomescape/reservation/ReservationDao.java +++ /dev/null @@ -1,127 +0,0 @@ -package roomescape.reservation; - -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.theme.Theme; -import roomescape.time.Time; - -import java.sql.PreparedStatement; -import java.util.List; - -@Repository -public class ReservationDao { - - private final JdbcTemplate jdbcTemplate; - - public ReservationDao(JdbcTemplate jdbcTemplate) { - this.jdbcTemplate = jdbcTemplate; - } - - public List findAll() { - return jdbcTemplate.query( - "SELECT r.id AS reservation_id, r.name as reservation_name, r.date as reservation_date, " + - "t.id AS theme_id, t.name AS theme_name, t.description AS theme_description, " + - "ti.id AS time_id, ti.time_value AS time_value " + - "FROM reservation r " + - "JOIN theme t ON r.theme_id = t.id " + - "JOIN time ti ON r.time_id = ti.id", - - (rs, rowNum) -> new Reservation( - rs.getLong("reservation_id"), - rs.getString("reservation_name"), - rs.getString("reservation_date"), - new Time( - rs.getLong("time_id"), - rs.getString("time_value") - ), - new Theme( - rs.getLong("theme_id"), - rs.getString("theme_name"), - rs.getString("theme_description") - ))); - } - - public Reservation save(ReservationRequest reservationRequest, String name) { - KeyHolder keyHolder = new GeneratedKeyHolder(); - jdbcTemplate.update(connection -> { - PreparedStatement ps = connection.prepareStatement("INSERT INTO reservation(date, name, theme_id, time_id) VALUES (?, ?, ?, ?)", new String[]{"id"}); - ps.setString(1, reservationRequest.getDate()); - ps.setString(2, name); - ps.setLong(3, reservationRequest.getTheme()); - ps.setLong(4, reservationRequest.getTime()); - return ps; - }, keyHolder); - - Time time = jdbcTemplate.queryForObject("SELECT * FROM time WHERE id = ?", - (rs, rowNum) -> new Time(rs.getLong("id"), rs.getString("time_value")), - reservationRequest.getTime()); - - Theme theme = jdbcTemplate.queryForObject("SELECT * FROM theme WHERE id = ?", - (rs, rowNum) -> new Theme(rs.getLong("id"), rs.getString("name"), rs.getString("description")), - reservationRequest.getTheme()); - - return new Reservation( - keyHolder.getKey().longValue(), - name, - reservationRequest.getDate(), - time, - theme - ); - } - - public void deleteById(Long id) { - jdbcTemplate.update("DELETE FROM reservation WHERE id = ?", id); - } - - public List findReservationsByDateAndTheme(String date, Long themeId) { - return jdbcTemplate.query( - "SELECT r.id AS reservation_id, r.name as reservation_name, r.date as reservation_date, " + - "t.id AS theme_id, t.name AS theme_name, t.description AS theme_description, " + - "ti.id AS time_id, ti.time_value AS time_value " + - "FROM reservation r " + - "JOIN theme t ON r.theme_id = t.id " + - "JOIN time ti ON r.time_id = ti.id" + - "WHERE r.date = ? AND r.theme_id = ?", - new Object[]{date, themeId}, - (rs, rowNum) -> new Reservation( - rs.getLong("reservation_id"), - rs.getString("reservation_name"), - rs.getString("reservation_date"), - new Time( - rs.getLong("time_id"), - rs.getString("time_value") - ), - new Theme( - rs.getLong("theme_id"), - rs.getString("theme_name"), - rs.getString("theme_description") - ))); - } - - public List findByDateAndThemeId(String date, Long themeId) { - return jdbcTemplate.query( - "SELECT r.id AS reservation_id, r.name as reservation_name, r.date as reservation_date, " + - "t.id AS theme_id, t.name AS theme_name, t.description AS theme_description, " + - "ti.id AS time_id, ti.time_value AS time_value " + - "FROM reservation r " + - "JOIN theme t ON r.theme_id = t.id " + - "JOIN time ti ON r.time_id = ti.id " + - "WHERE r.date = ? AND r.theme_id = ?", - new Object[]{date, themeId}, - (rs, rowNum) -> new Reservation( - rs.getLong("reservation_id"), - rs.getString("reservation_name"), - rs.getString("reservation_date"), - new Time( - rs.getLong("time_id"), - rs.getString("time_value") - ), - new Theme( - rs.getLong("theme_id"), - rs.getString("theme_name"), - rs.getString("theme_description") - ))); - } -} diff --git a/src/main/java/roomescape/reservation/ReservationRepository.java b/src/main/java/roomescape/reservation/ReservationRepository.java new file mode 100644 index 000000000..d8383df50 --- /dev/null +++ b/src/main/java/roomescape/reservation/ReservationRepository.java @@ -0,0 +1,13 @@ +package roomescape.reservation; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository +public interface ReservationRepository extends JpaRepository { + List findByDateAndThemeId(String date, Long themeId); + List findByMemberId(Long memberId); +} + diff --git a/src/main/java/roomescape/reservation/ReservationRequest.java b/src/main/java/roomescape/reservation/ReservationRequest.java index 19f441246..a377da524 100644 --- a/src/main/java/roomescape/reservation/ReservationRequest.java +++ b/src/main/java/roomescape/reservation/ReservationRequest.java @@ -1,24 +1,9 @@ package roomescape.reservation; -public class ReservationRequest { - private String name; - private String date; - private Long theme; - private Long time; - - public String getName() { - return name; - } - - public String getDate() { - return date; - } - - public Long getTheme() { - return theme; - } - - public Long getTime() { - return time; - } +public record ReservationRequest( + String name, + String date, + Long theme, + Long time +){ } diff --git a/src/main/java/roomescape/reservation/ReservationResponse.java b/src/main/java/roomescape/reservation/ReservationResponse.java index 41360a363..cdfc7c541 100644 --- a/src/main/java/roomescape/reservation/ReservationResponse.java +++ b/src/main/java/roomescape/reservation/ReservationResponse.java @@ -1,37 +1,9 @@ package roomescape.reservation; -public class ReservationResponse { - private Long id; - private String name; - private String theme; - private String date; - private String time; - - public ReservationResponse(Long id, String name, String theme, String date, String time) { - this.id = id; - this.name = name; - this.theme = theme; - this.date = date; - this.time = time; - } - - public Long getId() { - return id; - } - - public String getName() { - return name; - } - - public String getTheme() { - return theme; - } - - public String getDate() { - return date; - } - - public String getTime() { - return time; - } +public record ReservationResponse( + String name, + Long id, + String theme, + String date, + String time) { } diff --git a/src/main/java/roomescape/reservation/ReservationService.java b/src/main/java/roomescape/reservation/ReservationService.java index c392496dc..1ae612bf2 100644 --- a/src/main/java/roomescape/reservation/ReservationService.java +++ b/src/main/java/roomescape/reservation/ReservationService.java @@ -2,33 +2,96 @@ import org.springframework.stereotype.Service; import roomescape.login.LoginMember; +import roomescape.member.Member; +import roomescape.member.MemberRepository; +import roomescape.reservation.dto.MyReservationResponse; +import roomescape.theme.Theme; +import roomescape.theme.ThemeRepository; +import roomescape.time.Time; +import roomescape.time.TimeRepository; +import roomescape.waiting.Waiting; +import roomescape.waiting.WaitingRepository; +import java.util.ArrayList; import java.util.List; @Service public class ReservationService { - private ReservationDao reservationDao; + private final ReservationRepository reservationRepository; + private final ThemeRepository themeRepository; + private final TimeRepository timeRepository; + private final MemberRepository memberRepository; + private final WaitingRepository waitingRepository; - public ReservationService(ReservationDao reservationDao) { - this.reservationDao = reservationDao; + public ReservationService(ReservationRepository reservationRepository, ThemeRepository themeRepository, TimeRepository timeRepository, MemberRepository memberRepository, WaitingRepository waitingRepository) { + this.reservationRepository = reservationRepository; + this.themeRepository = themeRepository; + this.timeRepository = timeRepository; + this.memberRepository = memberRepository; + this.waitingRepository = waitingRepository; } public ReservationResponse save(ReservationRequest reservationRequest, LoginMember loginMember) { - String name = reservationRequest.getName(); + String name = reservationRequest.name(); if (name == null) { - name = loginMember.name(); + name = loginMember.getName(); } - Reservation reservation = reservationDao.save(reservationRequest, name); - return new ReservationResponse(reservation.getId(), reservation.getName(), reservation.getTheme().getName(), reservation.getDate(), reservation.getTime().getValue()); + Theme theme = themeRepository.findById(reservationRequest.theme()) + .orElseThrow(); + Time time = timeRepository.findById(reservationRequest.time()) + .orElseThrow(); + Member member = memberRepository.findByName(name) + .orElseThrow(); + Reservation reservation = Reservation.builder(). + member(member) + .date(reservationRequest.date()) + .time(time) + .theme(theme) + .build(); + reservationRepository.save(reservation); + return new ReservationResponse( + reservation.getMember().getName(), + reservation.getId(), + reservation.getTheme().getName(), + reservation.getDate(), + reservation.getTime().getTimeValue()); } public void deleteById(Long id) { - reservationDao.deleteById(id); + reservationRepository.deleteById(id); } public List findAll() { - return reservationDao.findAll().stream() - .map(it -> new ReservationResponse(it.getId(), it.getName(), it.getTheme().getName(), it.getDate(), it.getTime().getValue())) + return reservationRepository.findAll().stream() + .map(it -> new ReservationResponse(it.getMember().getName(), it.getId(), it.getTheme().getName(), it.getDate(), it.getTime().getTimeValue())) .toList(); } + + public List findMyReservations(LoginMember member) { + List result = new ArrayList<>(); + reservationRepository.findByMemberId(member.getId()) + .forEach(reservation -> + result.add(new MyReservationResponse( + reservation.getId(), + reservation.getTheme().getName(), + reservation.getDate(), + reservation.getTime().getTimeValue(), + "예약" + )) + ); + + waitingRepository.findWaitingsWithRankByMemberId(member.getId()) + .forEach(waitingWithRank ->{ + Waiting waiting = waitingWithRank.waiting(); + + result.add(new MyReservationResponse( + waiting.getId(), + waiting.getTheme().getName(), + waiting.getDate(), + waiting.getTime().getTimeValue(), + (waitingWithRank.rank()+1+"번째 예약대기") + )); + }); + return result; + } } diff --git a/src/main/java/roomescape/reservation/dto/MyReservationResponse.java b/src/main/java/roomescape/reservation/dto/MyReservationResponse.java new file mode 100644 index 000000000..35136057c --- /dev/null +++ b/src/main/java/roomescape/reservation/dto/MyReservationResponse.java @@ -0,0 +1,5 @@ +package roomescape.reservation.dto; + +public record MyReservationResponse(Long id, String theme, String date, String time, String status) { +} + diff --git a/src/main/java/roomescape/theme/Theme.java b/src/main/java/roomescape/theme/Theme.java index 430a6239c..8f3a4d944 100644 --- a/src/main/java/roomescape/theme/Theme.java +++ b/src/main/java/roomescape/theme/Theme.java @@ -1,10 +1,21 @@ package roomescape.theme; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import lombok.Getter; + +@Entity +@Getter public class Theme { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; private String description; + public Theme() { } @@ -19,15 +30,4 @@ public Theme(String name, String description) { this.description = description; } - public Long getId() { - return id; - } - - public String getName() { - return name; - } - - public String getDescription() { - return description; - } } diff --git a/src/main/java/roomescape/theme/ThemeController.java b/src/main/java/roomescape/theme/ThemeController.java index 03bca41a6..4286a0f69 100644 --- a/src/main/java/roomescape/theme/ThemeController.java +++ b/src/main/java/roomescape/theme/ThemeController.java @@ -13,26 +13,27 @@ @RestController public class ThemeController { - private ThemeDao themeDao; + private final ThemeService themeService; - public ThemeController(ThemeDao themeDao) { - this.themeDao = themeDao; + public ThemeController(ThemeService themeService) { + this.themeService = themeService; } @PostMapping("/themes") public ResponseEntity createTheme(@RequestBody Theme theme) { - Theme newTheme = themeDao.save(theme); + Theme newTheme = themeService.create(theme); return ResponseEntity.created(URI.create("/themes/" + newTheme.getId())).body(newTheme); } @GetMapping("/themes") public ResponseEntity> list() { - return ResponseEntity.ok(themeDao.findAll()); + + return ResponseEntity.ok(themeService.findAll()); } @DeleteMapping("/themes/{id}") public ResponseEntity deleteTheme(@PathVariable Long id) { - themeDao.deleteById(id); + themeService.delete(id); return ResponseEntity.noContent().build(); } } diff --git a/src/main/java/roomescape/theme/ThemeDao.java b/src/main/java/roomescape/theme/ThemeDao.java deleted file mode 100644 index 945341d8d..000000000 --- a/src/main/java/roomescape/theme/ThemeDao.java +++ /dev/null @@ -1,41 +0,0 @@ -package roomescape.theme; - -import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.jdbc.support.GeneratedKeyHolder; -import org.springframework.jdbc.support.KeyHolder; -import org.springframework.stereotype.Repository; - -import java.util.List; - -@Repository -public class ThemeDao { - private JdbcTemplate jdbcTemplate; - - public ThemeDao(JdbcTemplate jdbcTemplate) { - this.jdbcTemplate = jdbcTemplate; - } - - public List findAll() { - return jdbcTemplate.query("SELECT * FROM theme where deleted = false", (rs, rowNum) -> new Theme( - rs.getLong("id"), - rs.getString("name"), - rs.getString("description") - )); - } - - public Theme save(Theme theme) { - KeyHolder keyHolder = new GeneratedKeyHolder(); - jdbcTemplate.update(connection -> { - var ps = connection.prepareStatement("INSERT INTO theme(name, description) VALUES (?, ?)", new String[]{"id"}); - ps.setString(1, theme.getName()); - ps.setString(2, theme.getDescription()); - return ps; - }, keyHolder); - - return new Theme(keyHolder.getKey().longValue(), theme.getName(), theme.getDescription()); - } - - public void deleteById(Long id) { - jdbcTemplate.update("UPDATE theme SET deleted = true WHERE id = ?", id); - } -} diff --git a/src/main/java/roomescape/theme/ThemeRepository.java b/src/main/java/roomescape/theme/ThemeRepository.java new file mode 100644 index 000000000..304cb0ef1 --- /dev/null +++ b/src/main/java/roomescape/theme/ThemeRepository.java @@ -0,0 +1,8 @@ +package roomescape.theme; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface ThemeRepository extends JpaRepository { +} diff --git a/src/main/java/roomescape/theme/ThemeService.java b/src/main/java/roomescape/theme/ThemeService.java new file mode 100644 index 000000000..991c1aac8 --- /dev/null +++ b/src/main/java/roomescape/theme/ThemeService.java @@ -0,0 +1,28 @@ +package roomescape.theme; + +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +public class ThemeService { + private final ThemeRepository themeRepository; + + public ThemeService(ThemeRepository themeRepository){ + this.themeRepository=themeRepository; + } + + public Theme create(Theme theme){ + return themeRepository.save(theme); + } + + public void delete(Long id){ + themeRepository.deleteById(id); + } + + public List findAll(){ + return themeRepository.findAll(); + } + +} + diff --git a/src/main/java/roomescape/time/Time.java b/src/main/java/roomescape/time/Time.java index 008ed93cf..e79712741 100644 --- a/src/main/java/roomescape/time/Time.java +++ b/src/main/java/roomescape/time/Time.java @@ -1,27 +1,29 @@ package roomescape.time; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import lombok.Getter; + +@Entity +@Getter public class Time { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - private String value; + private String timeValue; public Time(Long id, String value) { this.id = id; - this.value = value; + this.timeValue = value; } public Time(String value) { - this.value = value; + this.timeValue = value; } public Time() { } - - public Long getId() { - return id; - } - - public String getValue() { - return value; - } } diff --git a/src/main/java/roomescape/time/TimeController.java b/src/main/java/roomescape/time/TimeController.java index 2343114d1..3850c6773 100644 --- a/src/main/java/roomescape/time/TimeController.java +++ b/src/main/java/roomescape/time/TimeController.java @@ -14,7 +14,7 @@ @RestController public class TimeController { - private TimeService timeService; + private final TimeService timeService; public TimeController(TimeService timeService) { this.timeService = timeService; @@ -27,7 +27,7 @@ public List