From 6b44d3d70821033a8be6384a24c7a42b555d9e90 Mon Sep 17 00:00:00 2001 From: squareCaaat <140076739+squareCaaat@users.noreply.github.com> Date: Mon, 25 Nov 2024 15:07:53 +0900 Subject: [PATCH 1/2] =?UTF-8?q?feat:=20=EC=A2=8B=EC=95=84=EC=9A=94=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cano_be/controller/MenuController.java | 38 +++++-------- .../java/com/wap/cano_be/domain/Like.java | 6 +- .../com/wap/cano_be/dto/menu/MenuLikeDto.java | 6 -- .../wap/cano_be/service/impl/LikeService.java | 55 ++++++++++++------- 4 files changed, 54 insertions(+), 51 deletions(-) delete mode 100644 src/main/java/com/wap/cano_be/dto/menu/MenuLikeDto.java diff --git a/src/main/java/com/wap/cano_be/controller/MenuController.java b/src/main/java/com/wap/cano_be/controller/MenuController.java index 7b74ebb..f8cdb50 100644 --- a/src/main/java/com/wap/cano_be/controller/MenuController.java +++ b/src/main/java/com/wap/cano_be/controller/MenuController.java @@ -129,27 +129,19 @@ public ResponseEntity reportMenu(@RequestBody MenuReportDto menuReportDto){ return getSuccessResponse(); } - // 좋아요 -// @PostMapping("/{menu_id}/like") -// public ResponseEntity setLike( -// @PathVariable("menu_id") long id, -// @RequestBody MenuLikeDto menuLikeDto, -// @AuthenticationPrincipal PrincipalDetail principalDetail){ -// -// if(menuLikeDto == null){ -// Map response = new HashMap<>(); -// response.put("error", "잘못된 요청 양식 입니다."); -// return ResponseEntity.badRequest().body(response); -// } -// -// Long memberId = principalDetail.getMember().getId(); -// if(memberId == null){ -// Map response = new HashMap<>(); -// response.put("error", "유효하지 않은 사용자입니다."); -// return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(response); -// } -// -// likeService.updateLike(memberId, id, menuLikeDto.like()); -// return getSuccessResponse(); -// } + // 좋아요 등록 + @PostMapping("/{menu_id}/like") + public ResponseEntity like( + @PathVariable("menu_id") long menuId, + @AuthenticationPrincipal PrincipalDetail principalDetail){ + return likeService.insert(principalDetail.getMember().getId(), menuId); + } + + // 좋아요 취소 + @DeleteMapping("/{menu_id}/like") + public ResponseEntity unlike( + @PathVariable("menu_id") long menuId, + @AuthenticationPrincipal PrincipalDetail principalDetail){ + return likeService.delete(principalDetail.getMember().getId(), menuId); + } } diff --git a/src/main/java/com/wap/cano_be/domain/Like.java b/src/main/java/com/wap/cano_be/domain/Like.java index d8c4227..efac382 100644 --- a/src/main/java/com/wap/cano_be/domain/Like.java +++ b/src/main/java/com/wap/cano_be/domain/Like.java @@ -1,6 +1,7 @@ package com.wap.cano_be.domain; import jakarta.persistence.*; +import lombok.Builder; @Entity @Table(name = "menu_like") @@ -8,16 +9,17 @@ public class Like { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @ManyToOne(targetEntity = Member.class, fetch = FetchType.LAZY) + @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "member_id") private Member member; - @ManyToOne(targetEntity = Menu.class, fetch = FetchType.LAZY) + @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "menu_id") private Menu menu; public Like() {} + @Builder public Like(Member member, Menu menu) { this.member = member; this.menu = menu; diff --git a/src/main/java/com/wap/cano_be/dto/menu/MenuLikeDto.java b/src/main/java/com/wap/cano_be/dto/menu/MenuLikeDto.java deleted file mode 100644 index 5a2e5fc..0000000 --- a/src/main/java/com/wap/cano_be/dto/menu/MenuLikeDto.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.wap.cano_be.dto.menu; - -public record MenuLikeDto( - boolean like -) { -} diff --git a/src/main/java/com/wap/cano_be/service/impl/LikeService.java b/src/main/java/com/wap/cano_be/service/impl/LikeService.java index 16538b6..81ba477 100644 --- a/src/main/java/com/wap/cano_be/service/impl/LikeService.java +++ b/src/main/java/com/wap/cano_be/service/impl/LikeService.java @@ -8,9 +8,12 @@ import com.wap.cano_be.repository.MenuRepository; import jakarta.transaction.Transactional; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; @Service +@Transactional public class LikeService { private final LikeRepository likeRepository; private final MemberRepository memberRepository; @@ -23,24 +26,36 @@ public LikeService(LikeRepository likeRepository, MemberRepository memberReposit this.menuRepository = menuRepository; } -// @Transactional -// public void updateLike(long memberId, long menuId, boolean like){ -// Member member = memberRepository.findBySocialId(memberId).orElseThrow(()->new IllegalArgumentException("Member not found")); -// Menu menu = menuRepository.findById(menuId); -// -// // 좋아요 했다면 -// if(like){ -// // member - menu 간 join이 없다면 -// if(!likeRepository.existsByMemberAndMenu(member, menu)){ -// menu.increaseLikeCount(); -// menuRepository.save(menu); // transactional 고려해 이후 제거할 수도 있음 -// likeRepository.save(new Like(member, menu)); -// } -// } else { -// // 좋아요 해제 -// menu.decreaseLikeCount(); -// menuRepository.save(menu); -// likeRepository.deleteByMemberAndMenu(member, menu); -// } -// } + public ResponseEntity insert(long memberId, long menuId){ + Member member = memberRepository.findById(memberId).orElseThrow(()->new IllegalArgumentException("Member not found")); + Menu menu = menuRepository.findById(menuId); + + // 이미 좋아요라면 409 에러 반환 + if(likeRepository.existsByMemberAndMenu(member, menu)){ + return ResponseEntity.status(HttpStatus.CONFLICT).build(); + } + + // 좋아요 반영 + Like like = Like.builder() + .member(member) + .menu(menu) + .build(); + likeRepository.save(like); + return ResponseEntity.noContent().build(); + } + + public ResponseEntity delete(long memberId, long menuId){ + Member member = memberRepository.findById(memberId).orElseThrow(()->new IllegalArgumentException("Member not found")); + Menu menu = menuRepository.findById(menuId); + + // 좋아요가 있다면 좋아요 해제 + if(likeRepository.existsByMemberAndMenu(member, menu)){ + likeRepository.deleteByMemberAndMenu(member, menu); + return ResponseEntity.noContent().build(); + } + + // 없으면 409 에러 반환 + return ResponseEntity.status(HttpStatus.CONFLICT).build(); + } + } From 45a7d627f762781fd98b21d88f4610ca66ee3bf2 Mon Sep 17 00:00:00 2001 From: squareCaaat <140076739+squareCaaat@users.noreply.github.com> Date: Mon, 25 Nov 2024 17:40:40 +0900 Subject: [PATCH 2/2] =?UTF-8?q?feat:=20=EC=A2=8B=EC=95=84=EC=9A=94=20?= =?UTF-8?q?=EC=97=B0=EA=B4=80=20=EA=B4=80=EA=B3=84=20=EB=A7=A4=ED=95=91=20?= =?UTF-8?q?=EB=B0=8F=20=EC=A2=8B=EC=95=84=EC=9A=94=ED=95=9C=20=EB=A9=94?= =?UTF-8?q?=EB=89=B4=20=EC=A1=B0=ED=9A=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cano_be/controller/LikeController.java | 41 +++++++++++++++++++ .../cano_be/controller/MenuController.java | 16 -------- .../java/com/wap/cano_be/domain/Like.java | 2 + .../java/com/wap/cano_be/domain/Member.java | 5 +++ .../wap/cano_be/service/impl/LikeService.java | 12 ++++++ 5 files changed, 60 insertions(+), 16 deletions(-) create mode 100644 src/main/java/com/wap/cano_be/controller/LikeController.java diff --git a/src/main/java/com/wap/cano_be/controller/LikeController.java b/src/main/java/com/wap/cano_be/controller/LikeController.java new file mode 100644 index 0000000..02f3ad9 --- /dev/null +++ b/src/main/java/com/wap/cano_be/controller/LikeController.java @@ -0,0 +1,41 @@ +package com.wap.cano_be.controller; + +import com.wap.cano_be.domain.PrincipalDetail; +import com.wap.cano_be.service.impl.LikeService; +import org.springframework.http.ResponseEntity; +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping("/api") +public class LikeController { + private final LikeService likeService; + + public LikeController(LikeService likeService) { + this.likeService = likeService; + } + + // 좋아요 등록 + @PostMapping("/menus/{menu_id}/like") + public ResponseEntity like( + @PathVariable("menu_id") long menuId, + @AuthenticationPrincipal PrincipalDetail principalDetail){ + return likeService.insert(principalDetail.getMember().getId(), menuId); + } + + // [TEST] 좋아요 한 메뉴 조회 + @GetMapping("/likes/me") + public ResponseEntity getLikes( + @AuthenticationPrincipal PrincipalDetail principalDetail + ) { + return likeService.getLikedMenus(principalDetail.getMember().getId()); + } + + // 좋아요 취소 + @DeleteMapping("/menus/{menu_id}/like") + public ResponseEntity unlike( + @PathVariable("menu_id") long menuId, + @AuthenticationPrincipal PrincipalDetail principalDetail){ + return likeService.delete(principalDetail.getMember().getId(), menuId); + } +} diff --git a/src/main/java/com/wap/cano_be/controller/MenuController.java b/src/main/java/com/wap/cano_be/controller/MenuController.java index f8cdb50..070285f 100644 --- a/src/main/java/com/wap/cano_be/controller/MenuController.java +++ b/src/main/java/com/wap/cano_be/controller/MenuController.java @@ -128,20 +128,4 @@ public ResponseEntity reportMenu(@RequestBody MenuReportDto menuReportDto){ log.info("menuReportDto: {}", menuReportDto); return getSuccessResponse(); } - - // 좋아요 등록 - @PostMapping("/{menu_id}/like") - public ResponseEntity like( - @PathVariable("menu_id") long menuId, - @AuthenticationPrincipal PrincipalDetail principalDetail){ - return likeService.insert(principalDetail.getMember().getId(), menuId); - } - - // 좋아요 취소 - @DeleteMapping("/{menu_id}/like") - public ResponseEntity unlike( - @PathVariable("menu_id") long menuId, - @AuthenticationPrincipal PrincipalDetail principalDetail){ - return likeService.delete(principalDetail.getMember().getId(), menuId); - } } diff --git a/src/main/java/com/wap/cano_be/domain/Like.java b/src/main/java/com/wap/cano_be/domain/Like.java index efac382..ee66a64 100644 --- a/src/main/java/com/wap/cano_be/domain/Like.java +++ b/src/main/java/com/wap/cano_be/domain/Like.java @@ -2,8 +2,10 @@ import jakarta.persistence.*; import lombok.Builder; +import lombok.Getter; @Entity +@Getter @Table(name = "menu_like") public class Like { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) diff --git a/src/main/java/com/wap/cano_be/domain/Member.java b/src/main/java/com/wap/cano_be/domain/Member.java index 850b24a..f6e02f5 100644 --- a/src/main/java/com/wap/cano_be/domain/Member.java +++ b/src/main/java/com/wap/cano_be/domain/Member.java @@ -6,6 +6,9 @@ import jakarta.persistence.*; import lombok.*; +import java.util.ArrayList; +import java.util.List; + @Entity @Getter @Setter @@ -32,4 +35,6 @@ public class Member { private MemberRole role; @Enumerated(EnumType.STRING) private Gender gender; + @OneToMany(mappedBy = "member", cascade = CascadeType.REMOVE, orphanRemoval = true) + private List likes = new ArrayList<>(); } diff --git a/src/main/java/com/wap/cano_be/service/impl/LikeService.java b/src/main/java/com/wap/cano_be/service/impl/LikeService.java index 81ba477..d2565a7 100644 --- a/src/main/java/com/wap/cano_be/service/impl/LikeService.java +++ b/src/main/java/com/wap/cano_be/service/impl/LikeService.java @@ -12,6 +12,9 @@ import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; +import java.util.List; +import java.util.stream.Collectors; + @Service @Transactional public class LikeService { @@ -58,4 +61,13 @@ public ResponseEntity delete(long memberId, long menuId){ return ResponseEntity.status(HttpStatus.CONFLICT).build(); } + // [TEST] 좋아요한 메뉴 찾기 + public ResponseEntity> getLikedMenus(long memberId){ + Member member = memberRepository.findById(memberId).orElseThrow(()->new IllegalArgumentException("Member not found")); + return ResponseEntity.ok().body( + member.getLikes().stream() + .map(Like::getMenu) + .collect(Collectors.toList())); + } + }