From fc45d3949e8c3837a8031b8d676a1521ea7f1222 Mon Sep 17 00:00:00 2001 From: BuildTools Date: Tue, 14 May 2024 21:01:22 +0900 Subject: [PATCH 01/18] =?UTF-8?q?feat=20:=20=EA=B2=8C=EC=8B=9C=EA=B8=80=20?= =?UTF-8?q?=EB=93=B1=EB=A1=9D=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../comment/entity/Comment.java | 56 +++++++++++++++++++ .../member/controller/MemberController.java | 6 +- .../controller/dto/request/MemberRequest.java | 3 +- .../dto/response/MemberResponse.java | 13 ++++- .../member/entity/Member.java | 9 ++- .../member/repository/MemberRepository.java | 2 +- .../repository/MemberRepositoryImpl.java | 2 +- .../member/service/MemberService.java | 2 - .../member/service/MemberServiceImpl.java | 10 ++-- .../post/controller/PostController.java | 42 ++++++++++++++ .../controller/dto/request/PostRequest.java | 35 ++++++++++++ .../dto/request/UpdatePostRequest.java | 14 +++++ .../controller/dto/response/PostResponse.java | 40 +++++++++++++ .../cow_mvc_practice/post/entity/Post.java | 30 +++++++++- .../post/repository/PostJPARepository.java | 6 ++ .../post/repository/PostRepository.java | 14 +++++ .../post/repository/PostRepositoryImpl.java | 27 +++++++++ .../post/service/PostService.java | 12 ++++ .../post/service/PostServiceImpl.java | 51 +++++++++++++++++ src/main/resources/application.yml | 2 +- .../CowMvcPracticeApplicationTests.java | 13 ----- .../NoArgsConstructorTest.java | 46 --------------- 22 files changed, 350 insertions(+), 85 deletions(-) create mode 100644 src/main/java/com/cow/cow_mvc_practice/comment/entity/Comment.java create mode 100644 src/main/java/com/cow/cow_mvc_practice/post/controller/PostController.java create mode 100644 src/main/java/com/cow/cow_mvc_practice/post/controller/dto/request/PostRequest.java create mode 100644 src/main/java/com/cow/cow_mvc_practice/post/controller/dto/request/UpdatePostRequest.java create mode 100644 src/main/java/com/cow/cow_mvc_practice/post/controller/dto/response/PostResponse.java create mode 100644 src/main/java/com/cow/cow_mvc_practice/post/repository/PostJPARepository.java create mode 100644 src/main/java/com/cow/cow_mvc_practice/post/repository/PostRepository.java create mode 100644 src/main/java/com/cow/cow_mvc_practice/post/repository/PostRepositoryImpl.java create mode 100644 src/main/java/com/cow/cow_mvc_practice/post/service/PostService.java create mode 100644 src/main/java/com/cow/cow_mvc_practice/post/service/PostServiceImpl.java delete mode 100644 src/test/java/com/cow/cow_mvc_practice/CowMvcPracticeApplicationTests.java delete mode 100644 src/test/java/com/cow/cow_mvc_practice/NoArgsConstructorTest.java diff --git a/src/main/java/com/cow/cow_mvc_practice/comment/entity/Comment.java b/src/main/java/com/cow/cow_mvc_practice/comment/entity/Comment.java new file mode 100644 index 0000000..4c2f042 --- /dev/null +++ b/src/main/java/com/cow/cow_mvc_practice/comment/entity/Comment.java @@ -0,0 +1,56 @@ +package com.cow.cow_mvc_practice.comment.entity; + +import com.cow.cow_mvc_practice.member.entity.Member; +import com.cow.cow_mvc_practice.post.entity.Post; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +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; + +@Entity +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class Comment { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "comment_id") + private Long id; + + private String content; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "post_id") + private Post post; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "member_id") + private Member member; + + @Builder + private Comment(final Long id, final String content) { + this.id = id; + this.content = content; + } + + public static Comment from(String content) { + return Comment.builder() + .content(content) + .build(); + } + + public static Comment of(Long id, String content) { + return Comment.builder() + .id(id) + .content(content) + .build(); + } + +} \ No newline at end of file diff --git a/src/main/java/com/cow/cow_mvc_practice/member/controller/MemberController.java b/src/main/java/com/cow/cow_mvc_practice/member/controller/MemberController.java index ab40c4f..2065f28 100644 --- a/src/main/java/com/cow/cow_mvc_practice/member/controller/MemberController.java +++ b/src/main/java/com/cow/cow_mvc_practice/member/controller/MemberController.java @@ -12,7 +12,6 @@ import com.cow.cow_mvc_practice.member.controller.dto.request.MemberRequest; import com.cow.cow_mvc_practice.member.controller.dto.response.MemberResponse; -import com.cow.cow_mvc_practice.member.entity.Member; import com.cow.cow_mvc_practice.member.service.MemberService; import lombok.RequiredArgsConstructor; @@ -54,9 +53,8 @@ public MemberResponse findMemberQuery(@RequestParam final Long memberId) { return memberService.findOne(memberId); } - @GetMapping("all") + @GetMapping("/all") public List findMembers() { return memberService.findAll(); } -} - +} \ No newline at end of file diff --git a/src/main/java/com/cow/cow_mvc_practice/member/controller/dto/request/MemberRequest.java b/src/main/java/com/cow/cow_mvc_practice/member/controller/dto/request/MemberRequest.java index c522eaf..dbfa263 100644 --- a/src/main/java/com/cow/cow_mvc_practice/member/controller/dto/request/MemberRequest.java +++ b/src/main/java/com/cow/cow_mvc_practice/member/controller/dto/request/MemberRequest.java @@ -5,7 +5,6 @@ import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; -import lombok.RequiredArgsConstructor; @Getter @AllArgsConstructor @@ -19,6 +18,6 @@ private MemberRequest(final String name) { } public static Member toEntity(String name) { - return Member.of(name); + return Member.from(name); } } diff --git a/src/main/java/com/cow/cow_mvc_practice/member/controller/dto/response/MemberResponse.java b/src/main/java/com/cow/cow_mvc_practice/member/controller/dto/response/MemberResponse.java index 25c83ef..ca35f5c 100644 --- a/src/main/java/com/cow/cow_mvc_practice/member/controller/dto/response/MemberResponse.java +++ b/src/main/java/com/cow/cow_mvc_practice/member/controller/dto/response/MemberResponse.java @@ -2,6 +2,8 @@ import com.cow.cow_mvc_practice.member.entity.Member; +import java.util.ArrayList; +import java.util.List; import lombok.Builder; import lombok.Getter; @@ -9,17 +11,22 @@ public class MemberResponse { private final Long id; private final String name; + private final List posts; @Builder - private MemberResponse(final Long id, final String name) { + private MemberResponse(final Long id, final String name, final List posts) { this.id = id; this.name = name; + this.posts = posts; } - public static MemberResponse of(final Member member) { + public static MemberResponse from(final Member member) { + List posts = new ArrayList<>(); + member.getPosts().forEach((p) -> posts.add(p.getTitle())); return MemberResponse.builder() .id(member.getId()) .name(member.getName()) + .posts(posts) .build(); } -} +} \ No newline at end of file diff --git a/src/main/java/com/cow/cow_mvc_practice/member/entity/Member.java b/src/main/java/com/cow/cow_mvc_practice/member/entity/Member.java index a904898..822b53e 100644 --- a/src/main/java/com/cow/cow_mvc_practice/member/entity/Member.java +++ b/src/main/java/com/cow/cow_mvc_practice/member/entity/Member.java @@ -1,5 +1,6 @@ package com.cow.cow_mvc_practice.member.entity; +import com.cow.cow_mvc_practice.comment.entity.Comment; import java.util.ArrayList; import java.util.List; @@ -8,7 +9,6 @@ import jakarta.persistence.CascadeType; import jakarta.persistence.Column; import jakarta.persistence.Entity; -import jakarta.persistence.FetchType; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; @@ -33,19 +33,22 @@ public class Member { @OneToMany(mappedBy = "member", cascade = CascadeType.ALL) private final List posts = new ArrayList<>(); + @OneToMany(mappedBy = "member", cascade = CascadeType.ALL) + private final List comments = new ArrayList<>(); + @Builder private Member(final Long id, final String name) { this.id = id; this.name = name; } - public static Member of(String name) { + public static Member from(String name) { return Member.builder() .name(name) .build(); } - public static Member from(Long id, String name) { + public static Member of(Long id, String name) { return Member.builder() .id(id) .name(name) diff --git a/src/main/java/com/cow/cow_mvc_practice/member/repository/MemberRepository.java b/src/main/java/com/cow/cow_mvc_practice/member/repository/MemberRepository.java index b9cd48b..f58f4c5 100644 --- a/src/main/java/com/cow/cow_mvc_practice/member/repository/MemberRepository.java +++ b/src/main/java/com/cow/cow_mvc_practice/member/repository/MemberRepository.java @@ -12,4 +12,4 @@ public interface MemberRepository { Optional findById(Long memberId); Optional> findAll(); -} +} \ No newline at end of file diff --git a/src/main/java/com/cow/cow_mvc_practice/member/repository/MemberRepositoryImpl.java b/src/main/java/com/cow/cow_mvc_practice/member/repository/MemberRepositoryImpl.java index dcfaceb..29fdffc 100644 --- a/src/main/java/com/cow/cow_mvc_practice/member/repository/MemberRepositoryImpl.java +++ b/src/main/java/com/cow/cow_mvc_practice/member/repository/MemberRepositoryImpl.java @@ -14,7 +14,7 @@ public class MemberRepositoryImpl implements MemberRepository { /** * 원래라면 HashMap이 아닌, concurrentHashMap이 적합함. HashMap은 멀티 쓰레드 환경에서 사용할 수 없기 때문.(동시성 이슈) */ - private static Map store = new HashMap<>(); + private static final Map store = new HashMap<>(); @Override diff --git a/src/main/java/com/cow/cow_mvc_practice/member/service/MemberService.java b/src/main/java/com/cow/cow_mvc_practice/member/service/MemberService.java index 06cc296..a68f749 100644 --- a/src/main/java/com/cow/cow_mvc_practice/member/service/MemberService.java +++ b/src/main/java/com/cow/cow_mvc_practice/member/service/MemberService.java @@ -1,11 +1,9 @@ package com.cow.cow_mvc_practice.member.service; -import java.util.ArrayList; import java.util.List; import com.cow.cow_mvc_practice.member.controller.dto.request.MemberRequest; import com.cow.cow_mvc_practice.member.controller.dto.response.MemberResponse; -import com.cow.cow_mvc_practice.member.entity.Member; public interface MemberService { diff --git a/src/main/java/com/cow/cow_mvc_practice/member/service/MemberServiceImpl.java b/src/main/java/com/cow/cow_mvc_practice/member/service/MemberServiceImpl.java index 9a63cc3..edcd37b 100644 --- a/src/main/java/com/cow/cow_mvc_practice/member/service/MemberServiceImpl.java +++ b/src/main/java/com/cow/cow_mvc_practice/member/service/MemberServiceImpl.java @@ -1,6 +1,5 @@ package com.cow.cow_mvc_practice.member.service; -import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; @@ -11,7 +10,6 @@ import com.cow.cow_mvc_practice.member.controller.dto.response.MemberResponse; import com.cow.cow_mvc_practice.member.entity.Member; import com.cow.cow_mvc_practice.member.repository.MemberJPARepository; -import com.cow.cow_mvc_practice.member.repository.MemberRepository; import jakarta.persistence.EntityNotFoundException; import lombok.RequiredArgsConstructor; @@ -41,9 +39,9 @@ public class MemberServiceImpl implements MemberService { /* MemberResponse dto 적용 */ @Override public MemberResponse join(MemberRequest memberRequest) { - Member member = Member.of(memberRequest.getName()); + Member member = Member.from(memberRequest.getName()); memberRepository.save(member); - return MemberResponse.of(member); + return MemberResponse.from(member); } @Transactional(readOnly = true) @@ -51,14 +49,14 @@ public MemberResponse join(MemberRequest memberRequest) { public MemberResponse findOne(Long memberId) { Member member = memberRepository.findById(memberId) .orElseThrow(() -> new EntityNotFoundException("[Error] 사용자를 찾을 수 없습니다.")); - return MemberResponse.of(member); + return MemberResponse.from(member); } @Override public List findAll() { List members = memberRepository.findAll(); return members.stream() - .map(MemberResponse::of) + .map(MemberResponse::from) .collect(Collectors.toList()); } } \ No newline at end of file diff --git a/src/main/java/com/cow/cow_mvc_practice/post/controller/PostController.java b/src/main/java/com/cow/cow_mvc_practice/post/controller/PostController.java new file mode 100644 index 0000000..1b4aec9 --- /dev/null +++ b/src/main/java/com/cow/cow_mvc_practice/post/controller/PostController.java @@ -0,0 +1,42 @@ +package com.cow.cow_mvc_practice.post.controller; + +import com.cow.cow_mvc_practice.post.controller.dto.request.PostRequest; +import com.cow.cow_mvc_practice.post.controller.dto.response.PostResponse; +import com.cow.cow_mvc_practice.post.service.PostService; +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/post") +@RequiredArgsConstructor +public class PostController { + + private final PostService postService; + + @PostMapping("/{memberId}/new") + public PostResponse create(@PathVariable final Long memberId ,@RequestBody final PostRequest postRequest) { + return postService.join(memberId, postRequest); + } + + @GetMapping("/{postId}") + public PostResponse findMember(@PathVariable final Long postId) { + return postService.findOne(postId); + } + + @GetMapping() + public PostResponse findPostQuery(@RequestParam final Long postId) { + return postService.findOne(postId); + } + + @GetMapping("all") + public List findPosts() { + return postService.findAll(); + } +} diff --git a/src/main/java/com/cow/cow_mvc_practice/post/controller/dto/request/PostRequest.java b/src/main/java/com/cow/cow_mvc_practice/post/controller/dto/request/PostRequest.java new file mode 100644 index 0000000..dbde191 --- /dev/null +++ b/src/main/java/com/cow/cow_mvc_practice/post/controller/dto/request/PostRequest.java @@ -0,0 +1,35 @@ +package com.cow.cow_mvc_practice.post.controller.dto.request; + +import com.cow.cow_mvc_practice.post.entity.Post; +import java.time.LocalDateTime; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import org.springframework.format.annotation.DateTimeFormat; + +@Getter +@AllArgsConstructor +public class PostRequest { + Long id; + final String title; + final String content; + @DateTimeFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss") + final LocalDateTime date; + + public PostRequest() { + this.title = ""; + this.content = ""; + this.date = LocalDateTime.now(); + } + + @Builder + private PostRequest(final String title, final String content, final LocalDateTime date) { + this.title = title; + this.content = content; + this.date = date; + } + + public static Post toEntity(String title, String content, LocalDateTime date) { + return Post.of(title, content, date); + } +} diff --git a/src/main/java/com/cow/cow_mvc_practice/post/controller/dto/request/UpdatePostRequest.java b/src/main/java/com/cow/cow_mvc_practice/post/controller/dto/request/UpdatePostRequest.java new file mode 100644 index 0000000..cd9f8cb --- /dev/null +++ b/src/main/java/com/cow/cow_mvc_practice/post/controller/dto/request/UpdatePostRequest.java @@ -0,0 +1,14 @@ +package com.cow.cow_mvc_practice.post.controller.dto.request; + +import com.cow.cow_mvc_practice.member.entity.Member; +import java.time.LocalDateTime; +import org.springframework.format.annotation.DateTimeFormat; + +public class UpdatePostRequest { + + private String title; + private String content; + private Member member; + @DateTimeFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss") + private LocalDateTime date; +} diff --git a/src/main/java/com/cow/cow_mvc_practice/post/controller/dto/response/PostResponse.java b/src/main/java/com/cow/cow_mvc_practice/post/controller/dto/response/PostResponse.java new file mode 100644 index 0000000..eba1b3b --- /dev/null +++ b/src/main/java/com/cow/cow_mvc_practice/post/controller/dto/response/PostResponse.java @@ -0,0 +1,40 @@ +package com.cow.cow_mvc_practice.post.controller.dto.response; + +import com.cow.cow_mvc_practice.post.entity.Post; +import com.fasterxml.jackson.annotation.JsonFormat; +import java.time.LocalDateTime; +import lombok.Builder; +import lombok.Getter; + +@Getter +public class PostResponse { + private final Long id; + + private final String title; + + private final String content; + + private final String memberName; + + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss", timezone = "Asia/Seoul") + final LocalDateTime date; + + @Builder + private PostResponse(final Long id, final String title, final String content, final String memberName, final LocalDateTime date) { + this.id = id; + this.title = title; + this.content = content; + this.memberName = memberName; + this.date = date; + } + + public static PostResponse from(final Post post) { + return PostResponse.builder() + .id(post.getId()) + .title(post.getTitle()) + .content(post.getContent()) + .memberName(post.getMember().getName()) + .date(post.getDate()) + .build(); + } +} diff --git a/src/main/java/com/cow/cow_mvc_practice/post/entity/Post.java b/src/main/java/com/cow/cow_mvc_practice/post/entity/Post.java index aec70d8..2d145bf 100644 --- a/src/main/java/com/cow/cow_mvc_practice/post/entity/Post.java +++ b/src/main/java/com/cow/cow_mvc_practice/post/entity/Post.java @@ -1,7 +1,11 @@ package com.cow.cow_mvc_practice.post.entity; +import com.cow.cow_mvc_practice.comment.entity.Comment; import com.cow.cow_mvc_practice.member.entity.Member; + +import com.fasterxml.jackson.annotation.JsonFormat; +import jakarta.persistence.CascadeType; import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.FetchType; @@ -10,6 +14,10 @@ import jakarta.persistence.Id; import jakarta.persistence.JoinColumn; import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToMany; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; @@ -28,22 +36,38 @@ public class Post { private String content; - @ManyToOne(fetch = FetchType.LAZY) + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss", timezone = "Asia/Seoul") + private LocalDateTime date; + + @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL) @JoinColumn(name = "member_id") private Member member; + @OneToMany(mappedBy = "post") + private final List comments = new ArrayList<>(); + @Builder - private Post(final String title, final String content, final Member member) { + private Post(final String title, final String content, final Member member, final LocalDateTime date) { this.title = title; this.content = content; this.member = member; + this.date = date; + } + + public static Post of(final String title, final String content, final LocalDateTime date) { + return Post.builder() + .title(title) + .content(content) + .date(date) + .build(); } - public static Post from(final String title, final String content, final Member member) { + public static Post of(final String title, final String content, final Member member, final LocalDateTime date) { return Post.builder() .title(title) .content(content) .member(member) + .date(date) .build(); } } \ No newline at end of file diff --git a/src/main/java/com/cow/cow_mvc_practice/post/repository/PostJPARepository.java b/src/main/java/com/cow/cow_mvc_practice/post/repository/PostJPARepository.java new file mode 100644 index 0000000..662b1aa --- /dev/null +++ b/src/main/java/com/cow/cow_mvc_practice/post/repository/PostJPARepository.java @@ -0,0 +1,6 @@ +package com.cow.cow_mvc_practice.post.repository; + +import com.cow.cow_mvc_practice.post.entity.Post; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface PostJPARepository extends JpaRepository {} \ No newline at end of file diff --git a/src/main/java/com/cow/cow_mvc_practice/post/repository/PostRepository.java b/src/main/java/com/cow/cow_mvc_practice/post/repository/PostRepository.java new file mode 100644 index 0000000..bf26ef9 --- /dev/null +++ b/src/main/java/com/cow/cow_mvc_practice/post/repository/PostRepository.java @@ -0,0 +1,14 @@ +package com.cow.cow_mvc_practice.post.repository; + +import com.cow.cow_mvc_practice.post.entity.Post; +import java.util.List; +import java.util.Optional; + +public interface PostRepository { + + void save(Post post); + + Optional findById(Long postId); + + Optional> findAll(); +} \ No newline at end of file diff --git a/src/main/java/com/cow/cow_mvc_practice/post/repository/PostRepositoryImpl.java b/src/main/java/com/cow/cow_mvc_practice/post/repository/PostRepositoryImpl.java new file mode 100644 index 0000000..47ffce4 --- /dev/null +++ b/src/main/java/com/cow/cow_mvc_practice/post/repository/PostRepositoryImpl.java @@ -0,0 +1,27 @@ +package com.cow.cow_mvc_practice.post.repository; + +import com.cow.cow_mvc_practice.post.entity.Post; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +public class PostRepositoryImpl implements PostRepository{ + + private static final Map store = new HashMap<>(); + + @Override + public void save(Post post) { + store.put(post.getId(), post); + } + + @Override + public Optional findById(Long memberId) { + return Optional.ofNullable(store.get(memberId)); + } + + @Override + public Optional> findAll() { + return Optional.of((List)store.values()); + } +} diff --git a/src/main/java/com/cow/cow_mvc_practice/post/service/PostService.java b/src/main/java/com/cow/cow_mvc_practice/post/service/PostService.java new file mode 100644 index 0000000..2fbd18c --- /dev/null +++ b/src/main/java/com/cow/cow_mvc_practice/post/service/PostService.java @@ -0,0 +1,12 @@ +package com.cow.cow_mvc_practice.post.service; + +import com.cow.cow_mvc_practice.post.controller.dto.request.PostRequest; +import com.cow.cow_mvc_practice.post.controller.dto.response.PostResponse; +import java.util.List; + +public interface PostService { + + PostResponse findOne(Long postId); + PostResponse join(Long memberId, PostRequest postRequest); + List findAll(); +} diff --git a/src/main/java/com/cow/cow_mvc_practice/post/service/PostServiceImpl.java b/src/main/java/com/cow/cow_mvc_practice/post/service/PostServiceImpl.java new file mode 100644 index 0000000..4c574fc --- /dev/null +++ b/src/main/java/com/cow/cow_mvc_practice/post/service/PostServiceImpl.java @@ -0,0 +1,51 @@ +package com.cow.cow_mvc_practice.post.service; + +import com.cow.cow_mvc_practice.member.entity.Member; +import com.cow.cow_mvc_practice.member.repository.MemberJPARepository; +import com.cow.cow_mvc_practice.post.controller.dto.request.PostRequest; +import com.cow.cow_mvc_practice.post.controller.dto.response.PostResponse; +import com.cow.cow_mvc_practice.post.entity.Post; +import com.cow.cow_mvc_practice.post.repository.PostJPARepository; +import jakarta.persistence.EntityNotFoundException; +import java.util.List; +import java.util.stream.Collectors; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@RequiredArgsConstructor +@Transactional +public class PostServiceImpl implements PostService{ + + private final PostJPARepository postRepository; + + @Autowired + private final MemberJPARepository memberRepository; + + @Override + public PostResponse join(Long memberId, PostRequest postRequest) { + Member member = memberRepository.findById(memberId) + .orElseThrow(() -> new EntityNotFoundException("[Error] 사용자를 찾을 수 없습니다.")); + Post post = Post.of(postRequest.getTitle(), postRequest.getContent(), member, postRequest.getDate()); + postRepository.save(post); + return PostResponse.from(post); + } + + @Transactional(readOnly = true) + @Override + public PostResponse findOne(Long postId) { + Post post = postRepository.findById(postId) + .orElseThrow(() -> new EntityNotFoundException("[Error] 게시글을 찾을 수 없습니다.")); + return PostResponse.from(post); + } + + @Override + public List findAll() { + List posts = postRepository.findAll(); + return posts.stream() + .map(PostResponse::from) + .collect(Collectors.toList()); + } +} diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 7819b3c..4425948 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -4,7 +4,7 @@ spring: jpa: open-in-view: true hibernate: - ddl-auto: validate + ddl-auto: create show-sql: true properties: hibernate: diff --git a/src/test/java/com/cow/cow_mvc_practice/CowMvcPracticeApplicationTests.java b/src/test/java/com/cow/cow_mvc_practice/CowMvcPracticeApplicationTests.java deleted file mode 100644 index c5b6306..0000000 --- a/src/test/java/com/cow/cow_mvc_practice/CowMvcPracticeApplicationTests.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.cow.cow_mvc_practice; - -import org.junit.jupiter.api.Test; -import org.springframework.boot.test.context.SpringBootTest; - -@SpringBootTest -class CowMvcPracticeApplicationTests { - - @Test - void contextLoads() { - } - -} diff --git a/src/test/java/com/cow/cow_mvc_practice/NoArgsConstructorTest.java b/src/test/java/com/cow/cow_mvc_practice/NoArgsConstructorTest.java deleted file mode 100644 index 721e958..0000000 --- a/src/test/java/com/cow/cow_mvc_practice/NoArgsConstructorTest.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.cow.cow_mvc_practice; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; -import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.ActiveProfiles; -import org.springframework.transaction.annotation.Transactional; -import org.testcontainers.junit.jupiter.Testcontainers; - -import com.cow.cow_mvc_practice.member.entity.Member; -import com.cow.cow_mvc_practice.post.entity.Post; - -import jakarta.persistence.EntityManager; - -@SpringBootTest -@Testcontainers -@ActiveProfiles("test") -@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) -public class NoArgsConstructorTest { - @Autowired - private EntityManager em; - - @BeforeEach - void makeEntity() { - Member member = Member.of("나바보"); - - em.persist(member); - - Post post = Post.from("글 제목입니다.", "글 내용입니다.", member); - em.persist(post); - } - - @Test - @Transactional - void proxyTest() { - - Post post = em.find(Post.class, 1L); - - System.out.println("post의 ID 값은 : " + post.getId()); - System.out.println("user의 ID 값은 : " + post.getMember().getId()); - } - -} From e9272f2eaafdab4f237b05d28585f0d6703fd674 Mon Sep 17 00:00:00 2001 From: BuildTools Date: Tue, 14 May 2024 22:41:52 +0900 Subject: [PATCH 02/18] =?UTF-8?q?feat=20:=20=ED=9A=8C=EC=9B=90=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../member/controller/MemberController.java | 6 ++++++ .../member/controller/dto/request/UpdateMemberRequest.java | 4 +++- .../cow/cow_mvc_practice/member/service/MemberService.java | 3 +-- .../cow_mvc_practice/member/service/MemberServiceImpl.java | 6 ++++++ .../cow_mvc_practice/post/controller/PostController.java | 2 +- 5 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/cow/cow_mvc_practice/member/controller/MemberController.java b/src/main/java/com/cow/cow_mvc_practice/member/controller/MemberController.java index 2065f28..f15ff22 100644 --- a/src/main/java/com/cow/cow_mvc_practice/member/controller/MemberController.java +++ b/src/main/java/com/cow/cow_mvc_practice/member/controller/MemberController.java @@ -2,6 +2,7 @@ import java.util.List; +import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; @@ -48,6 +49,11 @@ public MemberResponse findMember(@PathVariable final Long memberId) { return memberService.findOne(memberId); } + @DeleteMapping("/{memberId}/delete") + public String delete(@PathVariable final Long memberId) { + return memberService.delete(memberId); + } + @GetMapping() public MemberResponse findMemberQuery(@RequestParam final Long memberId) { return memberService.findOne(memberId); diff --git a/src/main/java/com/cow/cow_mvc_practice/member/controller/dto/request/UpdateMemberRequest.java b/src/main/java/com/cow/cow_mvc_practice/member/controller/dto/request/UpdateMemberRequest.java index 94429b9..33e3f76 100644 --- a/src/main/java/com/cow/cow_mvc_practice/member/controller/dto/request/UpdateMemberRequest.java +++ b/src/main/java/com/cow/cow_mvc_practice/member/controller/dto/request/UpdateMemberRequest.java @@ -1,9 +1,11 @@ package com.cow.cow_mvc_practice.member.controller.dto.request; +import lombok.AllArgsConstructor; import lombok.Getter; @Getter +@AllArgsConstructor public class UpdateMemberRequest { - private String name; + final String name; } diff --git a/src/main/java/com/cow/cow_mvc_practice/member/service/MemberService.java b/src/main/java/com/cow/cow_mvc_practice/member/service/MemberService.java index a68f749..bdb9703 100644 --- a/src/main/java/com/cow/cow_mvc_practice/member/service/MemberService.java +++ b/src/main/java/com/cow/cow_mvc_practice/member/service/MemberService.java @@ -11,10 +11,9 @@ public interface MemberService { // void join(MemberRequest memberRequest); // Member findOne(Long memberId); - /* MemberResponse dto 적용 */ MemberResponse findOne(Long memberId); MemberResponse join(MemberRequest memberRequest); List findAll(); + String delete(Long memberId); } - diff --git a/src/main/java/com/cow/cow_mvc_practice/member/service/MemberServiceImpl.java b/src/main/java/com/cow/cow_mvc_practice/member/service/MemberServiceImpl.java index edcd37b..7f2da4f 100644 --- a/src/main/java/com/cow/cow_mvc_practice/member/service/MemberServiceImpl.java +++ b/src/main/java/com/cow/cow_mvc_practice/member/service/MemberServiceImpl.java @@ -59,4 +59,10 @@ public List findAll() { .map(MemberResponse::from) .collect(Collectors.toList()); } + + @Override + public String delete(Long memberId) { + memberRepository.deleteById(memberId); + return "삭제에 성공하였습니다."; + } } \ No newline at end of file diff --git a/src/main/java/com/cow/cow_mvc_practice/post/controller/PostController.java b/src/main/java/com/cow/cow_mvc_practice/post/controller/PostController.java index 1b4aec9..c413a5f 100644 --- a/src/main/java/com/cow/cow_mvc_practice/post/controller/PostController.java +++ b/src/main/java/com/cow/cow_mvc_practice/post/controller/PostController.java @@ -20,7 +20,7 @@ public class PostController { private final PostService postService; - @PostMapping("/{memberId}/new") + @PostMapping("/members/{memberId}/new") public PostResponse create(@PathVariable final Long memberId ,@RequestBody final PostRequest postRequest) { return postService.join(memberId, postRequest); } From 6bac0b2db75edfa675fb475656188ca34e2e51fb Mon Sep 17 00:00:00 2001 From: BuildTools Date: Wed, 15 May 2024 16:54:46 +0900 Subject: [PATCH 03/18] =?UTF-8?q?refactor=20:=20=EA=B2=8C=EC=8B=9C?= =?UTF-8?q?=EA=B8=80=20=EC=83=9D=EC=84=B1=20URL=20=ED=98=95=EC=8B=9D=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../member/controller/MemberController.java | 18 ++++++++++++------ .../dto/response/MemberResponse.java | 4 ++++ .../post/controller/PostController.java | 7 ++++++- .../controller/dto/request/PostRequest.java | 5 ----- .../cow/cow_mvc_practice/post/entity/Post.java | 8 -------- .../post/service/PostService.java | 1 + src/main/resources/application.yml | 2 +- 7 files changed, 24 insertions(+), 21 deletions(-) diff --git a/src/main/java/com/cow/cow_mvc_practice/member/controller/MemberController.java b/src/main/java/com/cow/cow_mvc_practice/member/controller/MemberController.java index f15ff22..832f111 100644 --- a/src/main/java/com/cow/cow_mvc_practice/member/controller/MemberController.java +++ b/src/main/java/com/cow/cow_mvc_practice/member/controller/MemberController.java @@ -2,6 +2,7 @@ import java.util.List; +import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @@ -9,7 +10,7 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.ResponseBody; import com.cow.cow_mvc_practice.member.controller.dto.request.MemberRequest; import com.cow.cow_mvc_practice.member.controller.dto.response.MemberResponse; @@ -17,7 +18,7 @@ import lombok.RequiredArgsConstructor; -@RestController +@Controller @RequestMapping("/member") @RequiredArgsConstructor public class MemberController { @@ -40,12 +41,12 @@ public class MemberController { /* MemberResponse dto 적용 */ @PostMapping("/new") - public MemberResponse create(@RequestBody final MemberRequest memberRequest) { + public @ResponseBody MemberResponse create(@RequestBody final MemberRequest memberRequest) { return memberService.join(memberRequest); } @GetMapping("/{memberId}") - public MemberResponse findMember(@PathVariable final Long memberId) { + public @ResponseBody MemberResponse findMember(@PathVariable final Long memberId) { return memberService.findOne(memberId); } @@ -55,12 +56,17 @@ public String delete(@PathVariable final Long memberId) { } @GetMapping() - public MemberResponse findMemberQuery(@RequestParam final Long memberId) { + public @ResponseBody MemberResponse findMemberQuery(@RequestParam("id") final Long memberId) { return memberService.findOne(memberId); } @GetMapping("/all") - public List findMembers() { + public @ResponseBody List findMembers() { return memberService.findAll(); } + + @RequestMapping("/{memberId}/post/{path}") + public String redirectToPost(@PathVariable final Long memberId, @PathVariable final String path) { + return "forward:/post/"+memberId+"/"+path; + } } \ No newline at end of file diff --git a/src/main/java/com/cow/cow_mvc_practice/member/controller/dto/response/MemberResponse.java b/src/main/java/com/cow/cow_mvc_practice/member/controller/dto/response/MemberResponse.java index ca35f5c..6932b32 100644 --- a/src/main/java/com/cow/cow_mvc_practice/member/controller/dto/response/MemberResponse.java +++ b/src/main/java/com/cow/cow_mvc_practice/member/controller/dto/response/MemberResponse.java @@ -29,4 +29,8 @@ public static MemberResponse from(final Member member) { .posts(posts) .build(); } + + public static Member toEntity(final MemberResponse memberResponse) { + return Member.of(memberResponse.getId(), memberResponse.getName()); + } } \ No newline at end of file diff --git a/src/main/java/com/cow/cow_mvc_practice/post/controller/PostController.java b/src/main/java/com/cow/cow_mvc_practice/post/controller/PostController.java index c413a5f..2e45981 100644 --- a/src/main/java/com/cow/cow_mvc_practice/post/controller/PostController.java +++ b/src/main/java/com/cow/cow_mvc_practice/post/controller/PostController.java @@ -31,7 +31,7 @@ public PostResponse findMember(@PathVariable final Long postId) { } @GetMapping() - public PostResponse findPostQuery(@RequestParam final Long postId) { + public PostResponse findPostQuery(@RequestParam("id") final Long postId) { return postService.findOne(postId); } @@ -39,4 +39,9 @@ public PostResponse findPostQuery(@RequestParam final Long postId) { public List findPosts() { return postService.findAll(); } + + @PostMapping("/{memberId}/new") + public PostResponse create2(@PathVariable final Long memberId, @RequestBody final PostRequest postRequest) { + return postService.join(memberId, postRequest); + } } diff --git a/src/main/java/com/cow/cow_mvc_practice/post/controller/dto/request/PostRequest.java b/src/main/java/com/cow/cow_mvc_practice/post/controller/dto/request/PostRequest.java index dbde191..635546f 100644 --- a/src/main/java/com/cow/cow_mvc_practice/post/controller/dto/request/PostRequest.java +++ b/src/main/java/com/cow/cow_mvc_practice/post/controller/dto/request/PostRequest.java @@ -1,6 +1,5 @@ package com.cow.cow_mvc_practice.post.controller.dto.request; -import com.cow.cow_mvc_practice.post.entity.Post; import java.time.LocalDateTime; import lombok.AllArgsConstructor; import lombok.Builder; @@ -28,8 +27,4 @@ private PostRequest(final String title, final String content, final LocalDateTim this.content = content; this.date = date; } - - public static Post toEntity(String title, String content, LocalDateTime date) { - return Post.of(title, content, date); - } } diff --git a/src/main/java/com/cow/cow_mvc_practice/post/entity/Post.java b/src/main/java/com/cow/cow_mvc_practice/post/entity/Post.java index 2d145bf..4801eb8 100644 --- a/src/main/java/com/cow/cow_mvc_practice/post/entity/Post.java +++ b/src/main/java/com/cow/cow_mvc_practice/post/entity/Post.java @@ -54,14 +54,6 @@ private Post(final String title, final String content, final Member member, fina this.date = date; } - public static Post of(final String title, final String content, final LocalDateTime date) { - return Post.builder() - .title(title) - .content(content) - .date(date) - .build(); - } - public static Post of(final String title, final String content, final Member member, final LocalDateTime date) { return Post.builder() .title(title) diff --git a/src/main/java/com/cow/cow_mvc_practice/post/service/PostService.java b/src/main/java/com/cow/cow_mvc_practice/post/service/PostService.java index 2fbd18c..e1700ad 100644 --- a/src/main/java/com/cow/cow_mvc_practice/post/service/PostService.java +++ b/src/main/java/com/cow/cow_mvc_practice/post/service/PostService.java @@ -1,5 +1,6 @@ package com.cow.cow_mvc_practice.post.service; +import com.cow.cow_mvc_practice.member.entity.Member; import com.cow.cow_mvc_practice.post.controller.dto.request.PostRequest; import com.cow.cow_mvc_practice.post.controller.dto.response.PostResponse; import java.util.List; diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 4425948..7819b3c 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -4,7 +4,7 @@ spring: jpa: open-in-view: true hibernate: - ddl-auto: create + ddl-auto: validate show-sql: true properties: hibernate: From 033ebb93f01f56eb3b0411bd80db73a24b087ba8 Mon Sep 17 00:00:00 2001 From: BuildTools Date: Wed, 15 May 2024 16:56:16 +0900 Subject: [PATCH 04/18] =?UTF-8?q?refactor=20:=20=EA=B2=8C=EC=8B=9C?= =?UTF-8?q?=EA=B8=80=20=EC=83=9D=EC=84=B1=20URL=20=ED=98=95=EC=8B=9D=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../member/controller/dto/response/MemberResponse.java | 4 ---- .../com/cow/cow_mvc_practice/post/service/PostService.java | 1 - 2 files changed, 5 deletions(-) diff --git a/src/main/java/com/cow/cow_mvc_practice/member/controller/dto/response/MemberResponse.java b/src/main/java/com/cow/cow_mvc_practice/member/controller/dto/response/MemberResponse.java index 6932b32..ca35f5c 100644 --- a/src/main/java/com/cow/cow_mvc_practice/member/controller/dto/response/MemberResponse.java +++ b/src/main/java/com/cow/cow_mvc_practice/member/controller/dto/response/MemberResponse.java @@ -29,8 +29,4 @@ public static MemberResponse from(final Member member) { .posts(posts) .build(); } - - public static Member toEntity(final MemberResponse memberResponse) { - return Member.of(memberResponse.getId(), memberResponse.getName()); - } } \ No newline at end of file diff --git a/src/main/java/com/cow/cow_mvc_practice/post/service/PostService.java b/src/main/java/com/cow/cow_mvc_practice/post/service/PostService.java index e1700ad..2fbd18c 100644 --- a/src/main/java/com/cow/cow_mvc_practice/post/service/PostService.java +++ b/src/main/java/com/cow/cow_mvc_practice/post/service/PostService.java @@ -1,6 +1,5 @@ package com.cow.cow_mvc_practice.post.service; -import com.cow.cow_mvc_practice.member.entity.Member; import com.cow.cow_mvc_practice.post.controller.dto.request.PostRequest; import com.cow.cow_mvc_practice.post.controller.dto.response.PostResponse; import java.util.List; From 74decac169574fbeba97a7be057a56b297ec057c Mon Sep 17 00:00:00 2001 From: BuildTools Date: Wed, 15 May 2024 23:33:55 +0900 Subject: [PATCH 05/18] =?UTF-8?q?feat=20:=20=ED=9A=8C=EC=9B=90=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../member/controller/MemberController.java | 23 +++++++++++++++---- .../dto/request/UpdateMemberRequest.java | 2 +- .../member/entity/Member.java | 4 ++++ .../member/service/MemberService.java | 2 ++ .../member/service/MemberServiceImpl.java | 12 ++++++++++ 5 files changed, 37 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/cow/cow_mvc_practice/member/controller/MemberController.java b/src/main/java/com/cow/cow_mvc_practice/member/controller/MemberController.java index 832f111..bb312d0 100644 --- a/src/main/java/com/cow/cow_mvc_practice/member/controller/MemberController.java +++ b/src/main/java/com/cow/cow_mvc_practice/member/controller/MemberController.java @@ -1,10 +1,12 @@ package com.cow.cow_mvc_practice.member.controller; +import com.cow.cow_mvc_practice.member.controller.dto.request.UpdateMemberRequest; import java.util.List; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; @@ -40,33 +42,44 @@ public class MemberController { // /* MemberResponse dto 적용 */ + @ResponseBody @PostMapping("/new") - public @ResponseBody MemberResponse create(@RequestBody final MemberRequest memberRequest) { + public MemberResponse create(@RequestBody final MemberRequest memberRequest) { return memberService.join(memberRequest); } + @ResponseBody @GetMapping("/{memberId}") - public @ResponseBody MemberResponse findMember(@PathVariable final Long memberId) { + public MemberResponse findMember(@PathVariable final Long memberId) { return memberService.findOne(memberId); } + @ResponseBody @DeleteMapping("/{memberId}/delete") public String delete(@PathVariable final Long memberId) { return memberService.delete(memberId); } + @ResponseBody @GetMapping() - public @ResponseBody MemberResponse findMemberQuery(@RequestParam("id") final Long memberId) { + public MemberResponse findMemberQuery(@RequestParam("id") final Long memberId) { return memberService.findOne(memberId); } + @ResponseBody @GetMapping("/all") - public @ResponseBody List findMembers() { + public List findMembers() { return memberService.findAll(); } - @RequestMapping("/{memberId}/post/{path}") + @PostMapping("/{memberId}/post/{path}") public String redirectToPost(@PathVariable final Long memberId, @PathVariable final String path) { return "forward:/post/"+memberId+"/"+path; } + + @ResponseBody + @PatchMapping(value = "/{memberId}/update") + public MemberResponse update(@PathVariable final Long memberId, @RequestBody final UpdateMemberRequest updateMemberRequest) { + return memberService.updateById(memberId, updateMemberRequest); + } } \ No newline at end of file diff --git a/src/main/java/com/cow/cow_mvc_practice/member/controller/dto/request/UpdateMemberRequest.java b/src/main/java/com/cow/cow_mvc_practice/member/controller/dto/request/UpdateMemberRequest.java index 33e3f76..706870d 100644 --- a/src/main/java/com/cow/cow_mvc_practice/member/controller/dto/request/UpdateMemberRequest.java +++ b/src/main/java/com/cow/cow_mvc_practice/member/controller/dto/request/UpdateMemberRequest.java @@ -7,5 +7,5 @@ @AllArgsConstructor public class UpdateMemberRequest { - final String name; + final String name = null; } diff --git a/src/main/java/com/cow/cow_mvc_practice/member/entity/Member.java b/src/main/java/com/cow/cow_mvc_practice/member/entity/Member.java index 822b53e..cd30391 100644 --- a/src/main/java/com/cow/cow_mvc_practice/member/entity/Member.java +++ b/src/main/java/com/cow/cow_mvc_practice/member/entity/Member.java @@ -54,4 +54,8 @@ public static Member of(Long id, String name) { .name(name) .build(); } + + public void updateMember(String name) { + this.name = name; + } } diff --git a/src/main/java/com/cow/cow_mvc_practice/member/service/MemberService.java b/src/main/java/com/cow/cow_mvc_practice/member/service/MemberService.java index bdb9703..5feaa0b 100644 --- a/src/main/java/com/cow/cow_mvc_practice/member/service/MemberService.java +++ b/src/main/java/com/cow/cow_mvc_practice/member/service/MemberService.java @@ -1,5 +1,6 @@ package com.cow.cow_mvc_practice.member.service; +import com.cow.cow_mvc_practice.member.controller.dto.request.UpdateMemberRequest; import java.util.List; import com.cow.cow_mvc_practice.member.controller.dto.request.MemberRequest; @@ -16,4 +17,5 @@ public interface MemberService { MemberResponse join(MemberRequest memberRequest); List findAll(); String delete(Long memberId); + MemberResponse updateById(Long memberId, UpdateMemberRequest updateMemberRequest); } diff --git a/src/main/java/com/cow/cow_mvc_practice/member/service/MemberServiceImpl.java b/src/main/java/com/cow/cow_mvc_practice/member/service/MemberServiceImpl.java index 7f2da4f..35f7565 100644 --- a/src/main/java/com/cow/cow_mvc_practice/member/service/MemberServiceImpl.java +++ b/src/main/java/com/cow/cow_mvc_practice/member/service/MemberServiceImpl.java @@ -1,6 +1,8 @@ package com.cow.cow_mvc_practice.member.service; +import com.cow.cow_mvc_practice.member.controller.dto.request.UpdateMemberRequest; import java.util.List; +import java.util.Optional; import java.util.stream.Collectors; import org.springframework.stereotype.Service; @@ -65,4 +67,14 @@ public String delete(Long memberId) { memberRepository.deleteById(memberId); return "삭제에 성공하였습니다."; } + + @Transactional + @Override + public MemberResponse updateById(Long memberId, UpdateMemberRequest updateMemberRequest) { + Member member = memberRepository.findById(memberId) + .orElseThrow(() -> new EntityNotFoundException("[Error] 사용자를 찾을 수 없습니다.")); + String name = Optional.ofNullable(updateMemberRequest.getName()).orElse(member.getName()); + member.updateMember(name); + return MemberResponse.from(member); + } } \ No newline at end of file From f5ff27b48838b33c20f989219f8bd2b806b63014 Mon Sep 17 00:00:00 2001 From: BuildTools Date: Fri, 17 May 2024 20:20:20 +0900 Subject: [PATCH 06/18] =?UTF-8?q?refactor=20:=20Post=20=EC=83=9D=EC=84=B1?= =?UTF-8?q?=20=EC=8B=9C=20=EC=9E=91=EC=84=B1=20=EC=9D=BC=EC=9E=90=20?= =?UTF-8?q?=EC=9E=84=EC=9D=98=20=EB=B6=80=EC=97=AC=20=EC=A0=9C=ED=95=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../post/controller/dto/request/PostRequest.java | 5 ----- .../post/controller/dto/request/UpdatePostRequest.java | 4 ---- .../cow/cow_mvc_practice/post/service/PostServiceImpl.java | 3 ++- 3 files changed, 2 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/cow/cow_mvc_practice/post/controller/dto/request/PostRequest.java b/src/main/java/com/cow/cow_mvc_practice/post/controller/dto/request/PostRequest.java index 635546f..5c6ef08 100644 --- a/src/main/java/com/cow/cow_mvc_practice/post/controller/dto/request/PostRequest.java +++ b/src/main/java/com/cow/cow_mvc_practice/post/controller/dto/request/PostRequest.java @@ -4,7 +4,6 @@ import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; -import org.springframework.format.annotation.DateTimeFormat; @Getter @AllArgsConstructor @@ -12,19 +11,15 @@ public class PostRequest { Long id; final String title; final String content; - @DateTimeFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss") - final LocalDateTime date; public PostRequest() { this.title = ""; this.content = ""; - this.date = LocalDateTime.now(); } @Builder private PostRequest(final String title, final String content, final LocalDateTime date) { this.title = title; this.content = content; - this.date = date; } } diff --git a/src/main/java/com/cow/cow_mvc_practice/post/controller/dto/request/UpdatePostRequest.java b/src/main/java/com/cow/cow_mvc_practice/post/controller/dto/request/UpdatePostRequest.java index cd9f8cb..de822bb 100644 --- a/src/main/java/com/cow/cow_mvc_practice/post/controller/dto/request/UpdatePostRequest.java +++ b/src/main/java/com/cow/cow_mvc_practice/post/controller/dto/request/UpdatePostRequest.java @@ -1,14 +1,10 @@ package com.cow.cow_mvc_practice.post.controller.dto.request; import com.cow.cow_mvc_practice.member.entity.Member; -import java.time.LocalDateTime; -import org.springframework.format.annotation.DateTimeFormat; public class UpdatePostRequest { private String title; private String content; private Member member; - @DateTimeFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss") - private LocalDateTime date; } diff --git a/src/main/java/com/cow/cow_mvc_practice/post/service/PostServiceImpl.java b/src/main/java/com/cow/cow_mvc_practice/post/service/PostServiceImpl.java index 4c574fc..5f64312 100644 --- a/src/main/java/com/cow/cow_mvc_practice/post/service/PostServiceImpl.java +++ b/src/main/java/com/cow/cow_mvc_practice/post/service/PostServiceImpl.java @@ -7,6 +7,7 @@ import com.cow.cow_mvc_practice.post.entity.Post; import com.cow.cow_mvc_practice.post.repository.PostJPARepository; import jakarta.persistence.EntityNotFoundException; +import java.time.LocalDateTime; import java.util.List; import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; @@ -28,7 +29,7 @@ public class PostServiceImpl implements PostService{ public PostResponse join(Long memberId, PostRequest postRequest) { Member member = memberRepository.findById(memberId) .orElseThrow(() -> new EntityNotFoundException("[Error] 사용자를 찾을 수 없습니다.")); - Post post = Post.of(postRequest.getTitle(), postRequest.getContent(), member, postRequest.getDate()); + Post post = Post.of(postRequest.getTitle(), postRequest.getContent(), member, LocalDateTime.now()); postRepository.save(post); return PostResponse.from(post); } From c3ace06995041e3d1512e64d2522f6e59e446b4b Mon Sep 17 00:00:00 2001 From: BuildTools Date: Sat, 18 May 2024 20:51:23 +0900 Subject: [PATCH 07/18] =?UTF-8?q?refactor=20:=20=EB=A6=AC=EB=8B=A4?= =?UTF-8?q?=EC=9D=B4=EB=A0=89=EC=85=98=20=EC=82=AD=EC=A0=9C,=20URL=20?= =?UTF-8?q?=ED=98=95=EC=8B=9D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../comment/controller/CommentController.java | 51 +++++++++++++ .../dto/request/CommentRequest.java | 11 +++ .../dto/request/UpdateCommentRequest.java | 10 +++ .../dto/response/CommentResponse.java | 32 +++++++++ .../comment/entity/Comment.java | 23 +++--- .../repository/CommentJPARepository.java | 11 +++ .../comment/service/CommentService.java | 13 ++++ .../comment/service/CommentServiceImpl.java | 72 +++++++++++++++++++ .../member/controller/MemberController.java | 42 +++-------- .../controller/dto/request/MemberRequest.java | 20 ++---- .../dto/request/UpdateMemberRequest.java | 7 +- .../member/service/MemberServiceImpl.java | 21 +----- .../post/controller/PostController.java | 15 ++-- .../controller/dto/request/PostRequest.java | 24 ++----- .../dto/request/UpdatePostRequest.java | 7 +- .../controller/dto/response/PostResponse.java | 15 +++- .../post/repository/PostJPARepository.java | 5 +- .../post/service/PostService.java | 1 + .../post/service/PostServiceImpl.java | 12 +++- 19 files changed, 277 insertions(+), 115 deletions(-) create mode 100644 src/main/java/com/cow/cow_mvc_practice/comment/controller/CommentController.java create mode 100644 src/main/java/com/cow/cow_mvc_practice/comment/controller/dto/request/CommentRequest.java create mode 100644 src/main/java/com/cow/cow_mvc_practice/comment/controller/dto/request/UpdateCommentRequest.java create mode 100644 src/main/java/com/cow/cow_mvc_practice/comment/controller/dto/response/CommentResponse.java create mode 100644 src/main/java/com/cow/cow_mvc_practice/comment/repository/CommentJPARepository.java create mode 100644 src/main/java/com/cow/cow_mvc_practice/comment/service/CommentService.java create mode 100644 src/main/java/com/cow/cow_mvc_practice/comment/service/CommentServiceImpl.java diff --git a/src/main/java/com/cow/cow_mvc_practice/comment/controller/CommentController.java b/src/main/java/com/cow/cow_mvc_practice/comment/controller/CommentController.java new file mode 100644 index 0000000..aa90fa8 --- /dev/null +++ b/src/main/java/com/cow/cow_mvc_practice/comment/controller/CommentController.java @@ -0,0 +1,51 @@ +package com.cow.cow_mvc_practice.comment.controller; + +import com.cow.cow_mvc_practice.comment.controller.dto.request.CommentRequest; +import com.cow.cow_mvc_practice.comment.controller.dto.response.CommentResponse; +import com.cow.cow_mvc_practice.comment.service.CommentService; +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/comment") +@RequiredArgsConstructor +public class CommentController { + private final CommentService commentService; + + @PostMapping("/new/member/{memberId}/post/{postId}") + public CommentResponse create(@PathVariable final Long memberId, @PathVariable final Long postId, @RequestBody final CommentRequest commentRequest) { + return commentService.join(memberId, postId, commentRequest); + } + + @GetMapping("/{commentId}") + public CommentResponse findMember(@PathVariable final Long commentId) { + return commentService.findOne(commentId); + } + + @GetMapping() + public CommentResponse findCommentQuery(@RequestParam("id") final Long commentId) { + return commentService.findOne(commentId); + } + + @GetMapping("all") + public List findComments() { + return commentService.findAll(); + } + + @GetMapping("/all/member/{memberId}") + public List findCommentsByMember(@PathVariable final Long memberId) { + return commentService.findAllByMember(memberId); + } + + @GetMapping("/all/post/{postId}") + public List findCommentsByPost(@PathVariable final Long postId) { + return commentService.findAllByPost(postId); + } +} \ No newline at end of file diff --git a/src/main/java/com/cow/cow_mvc_practice/comment/controller/dto/request/CommentRequest.java b/src/main/java/com/cow/cow_mvc_practice/comment/controller/dto/request/CommentRequest.java new file mode 100644 index 0000000..f4bf57d --- /dev/null +++ b/src/main/java/com/cow/cow_mvc_practice/comment/controller/dto/request/CommentRequest.java @@ -0,0 +1,11 @@ +package com.cow.cow_mvc_practice.comment.controller.dto.request; + +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +public class CommentRequest { + private String title; + private String content; +} \ No newline at end of file diff --git a/src/main/java/com/cow/cow_mvc_practice/comment/controller/dto/request/UpdateCommentRequest.java b/src/main/java/com/cow/cow_mvc_practice/comment/controller/dto/request/UpdateCommentRequest.java new file mode 100644 index 0000000..22823b3 --- /dev/null +++ b/src/main/java/com/cow/cow_mvc_practice/comment/controller/dto/request/UpdateCommentRequest.java @@ -0,0 +1,10 @@ +package com.cow.cow_mvc_practice.comment.controller.dto.request; + +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +public class UpdateCommentRequest { + private String title; +} diff --git a/src/main/java/com/cow/cow_mvc_practice/comment/controller/dto/response/CommentResponse.java b/src/main/java/com/cow/cow_mvc_practice/comment/controller/dto/response/CommentResponse.java new file mode 100644 index 0000000..eda5b90 --- /dev/null +++ b/src/main/java/com/cow/cow_mvc_practice/comment/controller/dto/response/CommentResponse.java @@ -0,0 +1,32 @@ +package com.cow.cow_mvc_practice.comment.controller.dto.response; + +import com.cow.cow_mvc_practice.comment.entity.Comment; +import com.fasterxml.jackson.annotation.JsonFormat; +import java.time.LocalDateTime; +import lombok.Builder; +import lombok.Getter; + +@Getter +public class CommentResponse { + private final Long id; + + private final String content; + + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss", timezone = "Asia/Seoul") + private final LocalDateTime date; + + @Builder + private CommentResponse(final Long id, final String content, final LocalDateTime date) { + this.id = id; + this.content = content; + this.date = date; + } + + public static CommentResponse from(final Comment comment) { + return CommentResponse.builder() + .id(comment.getId()) + .content(comment.getContent()) + .date(comment.getDate()) + .build(); + } +} \ No newline at end of file diff --git a/src/main/java/com/cow/cow_mvc_practice/comment/entity/Comment.java b/src/main/java/com/cow/cow_mvc_practice/comment/entity/Comment.java index 4c2f042..a2d7fe5 100644 --- a/src/main/java/com/cow/cow_mvc_practice/comment/entity/Comment.java +++ b/src/main/java/com/cow/cow_mvc_practice/comment/entity/Comment.java @@ -2,6 +2,7 @@ import com.cow.cow_mvc_practice.member.entity.Member; import com.cow.cow_mvc_practice.post.entity.Post; +import com.fasterxml.jackson.annotation.JsonFormat; import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.FetchType; @@ -10,6 +11,7 @@ import jakarta.persistence.Id; import jakarta.persistence.JoinColumn; import jakarta.persistence.ManyToOne; +import java.time.LocalDateTime; import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; @@ -26,6 +28,9 @@ public class Comment { private String content; + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss", timezone = "Asia/Seoul") + private LocalDateTime date; + @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "post_id") private Post post; @@ -35,22 +40,20 @@ public class Comment { private Member member; @Builder - private Comment(final Long id, final String content) { + private Comment(final Long id, final String content, final LocalDateTime date, Post post, Member member) { this.id = id; this.content = content; + this.date = date; + this.post = post; + this.member = member; } - public static Comment from(String content) { + public static Comment of(String content, LocalDateTime date, Post post, Member member) { return Comment.builder() .content(content) + .date(date) + .post(post) + .member(member) .build(); } - - public static Comment of(Long id, String content) { - return Comment.builder() - .id(id) - .content(content) - .build(); - } - } \ No newline at end of file diff --git a/src/main/java/com/cow/cow_mvc_practice/comment/repository/CommentJPARepository.java b/src/main/java/com/cow/cow_mvc_practice/comment/repository/CommentJPARepository.java new file mode 100644 index 0000000..e774562 --- /dev/null +++ b/src/main/java/com/cow/cow_mvc_practice/comment/repository/CommentJPARepository.java @@ -0,0 +1,11 @@ +package com.cow.cow_mvc_practice.comment.repository; + +import com.cow.cow_mvc_practice.comment.entity.Comment; +import java.util.List; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface CommentJPARepository extends JpaRepository { + List findAllByMemberId(Long memberId); + + List findAllByPostId(Long postId); +} \ No newline at end of file diff --git a/src/main/java/com/cow/cow_mvc_practice/comment/service/CommentService.java b/src/main/java/com/cow/cow_mvc_practice/comment/service/CommentService.java new file mode 100644 index 0000000..2cb4cc0 --- /dev/null +++ b/src/main/java/com/cow/cow_mvc_practice/comment/service/CommentService.java @@ -0,0 +1,13 @@ +package com.cow.cow_mvc_practice.comment.service; + +import com.cow.cow_mvc_practice.comment.controller.dto.request.CommentRequest; +import com.cow.cow_mvc_practice.comment.controller.dto.response.CommentResponse; +import java.util.List; + +public interface CommentService { + CommentResponse findOne(Long commentId); + CommentResponse join(Long memberId, Long postId, CommentRequest commentRequest); + List findAllByPost(Long postId); + List findAllByMember(Long memberId); + List findAll(); +} diff --git a/src/main/java/com/cow/cow_mvc_practice/comment/service/CommentServiceImpl.java b/src/main/java/com/cow/cow_mvc_practice/comment/service/CommentServiceImpl.java new file mode 100644 index 0000000..db587b1 --- /dev/null +++ b/src/main/java/com/cow/cow_mvc_practice/comment/service/CommentServiceImpl.java @@ -0,0 +1,72 @@ +package com.cow.cow_mvc_practice.comment.service; + +import com.cow.cow_mvc_practice.comment.controller.dto.request.CommentRequest; +import com.cow.cow_mvc_practice.comment.controller.dto.response.CommentResponse; +import com.cow.cow_mvc_practice.comment.entity.Comment; +import com.cow.cow_mvc_practice.comment.repository.CommentJPARepository; +import com.cow.cow_mvc_practice.member.entity.Member; +import com.cow.cow_mvc_practice.member.repository.MemberJPARepository; +import com.cow.cow_mvc_practice.post.entity.Post; +import com.cow.cow_mvc_practice.post.repository.PostJPARepository; +import jakarta.persistence.EntityNotFoundException; +import java.time.LocalDateTime; +import java.util.List; +import java.util.stream.Collectors; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@RequiredArgsConstructor +@Transactional +public class CommentServiceImpl implements CommentService { + private final CommentJPARepository commentRepository; + private final MemberJPARepository memberRepository; + private final PostJPARepository postRepository; + + @Transactional(readOnly = true) + @Override + public CommentResponse findOne(Long commentId) { + Comment comment = commentRepository.findById(commentId) + .orElseThrow(() -> new EntityNotFoundException("[Error] 댓글을 찾을 수 없습니다.")); + return CommentResponse.from(comment); + } + + @Override + public CommentResponse join(Long memberId, Long postId, CommentRequest commentRequest) { + Member member = this.memberRepository.findById(memberId) + .orElseThrow(() -> new EntityNotFoundException("[Error] 사용자를 찾을 수 없습니다.")); + Post post = this.postRepository.findById(postId) + .orElseThrow(() -> new EntityNotFoundException("[Error] 게시글을 찾을 수 없습니다.")); + Comment comment = Comment.of(commentRequest.getContent(), LocalDateTime.now(), post, member); + commentRepository.save(comment); + return CommentResponse.from(comment); + } + + @Transactional(readOnly = true) + @Override + public List findAllByPost(Long postId) { + List comments = commentRepository.findAllByPostId(postId); + return comments.stream() + .map(CommentResponse::from) + .collect(Collectors.toList()); + } + + @Transactional(readOnly = true) + @Override + public List findAllByMember(Long memberId) { + List comments = commentRepository.findAllByMemberId(memberId); + return comments.stream() + .map(CommentResponse::from) + .collect(Collectors.toList()); + } + + @Transactional(readOnly = true) + @Override + public List findAll() { + List comments = commentRepository.findAll(); + return comments.stream() + .map(CommentResponse::from) + .collect(Collectors.toList()); + } +} diff --git a/src/main/java/com/cow/cow_mvc_practice/member/controller/MemberController.java b/src/main/java/com/cow/cow_mvc_practice/member/controller/MemberController.java index bb312d0..cedd37f 100644 --- a/src/main/java/com/cow/cow_mvc_practice/member/controller/MemberController.java +++ b/src/main/java/com/cow/cow_mvc_practice/member/controller/MemberController.java @@ -3,7 +3,6 @@ import com.cow.cow_mvc_practice.member.controller.dto.request.UpdateMemberRequest; import java.util.List; -import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PatchMapping; @@ -12,74 +11,49 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.ResponseBody; import com.cow.cow_mvc_practice.member.controller.dto.request.MemberRequest; import com.cow.cow_mvc_practice.member.controller.dto.response.MemberResponse; import com.cow.cow_mvc_practice.member.service.MemberService; import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.RestController; -@Controller +@RestController @RequestMapping("/member") @RequiredArgsConstructor public class MemberController { private final MemberService memberService; - /* 기본 */ - // @PostMapping("/new") - // public String create(@RequestBody final MemberRequest memberRequest) { - // memberService.join(memberRequest); - // return "회원저장 성공!"; - // } - // - // @GetMapping("/{memberId}") - // public String findMember(@PathVariable final Long memberId) { - // Member member = memberService.findOne(memberId); - // return "member 아이디: " + member.getId() + ", member 이름: " + member.getName(); - // } - // - /* MemberResponse dto 적용 */ - @ResponseBody @PostMapping("/new") public MemberResponse create(@RequestBody final MemberRequest memberRequest) { return memberService.join(memberRequest); } - @ResponseBody @GetMapping("/{memberId}") public MemberResponse findMember(@PathVariable final Long memberId) { return memberService.findOne(memberId); } - @ResponseBody - @DeleteMapping("/{memberId}/delete") - public String delete(@PathVariable final Long memberId) { - return memberService.delete(memberId); - } - - @ResponseBody @GetMapping() public MemberResponse findMemberQuery(@RequestParam("id") final Long memberId) { return memberService.findOne(memberId); } - @ResponseBody @GetMapping("/all") public List findMembers() { return memberService.findAll(); } - @PostMapping("/{memberId}/post/{path}") - public String redirectToPost(@PathVariable final Long memberId, @PathVariable final String path) { - return "forward:/post/"+memberId+"/"+path; - } - - @ResponseBody - @PatchMapping(value = "/{memberId}/update") + @PatchMapping(value = "/{memberId}") public MemberResponse update(@PathVariable final Long memberId, @RequestBody final UpdateMemberRequest updateMemberRequest) { return memberService.updateById(memberId, updateMemberRequest); } + + @DeleteMapping("/{memberId}") + public String delete(@PathVariable final Long memberId) { + return memberService.delete(memberId); + } } \ No newline at end of file diff --git a/src/main/java/com/cow/cow_mvc_practice/member/controller/dto/request/MemberRequest.java b/src/main/java/com/cow/cow_mvc_practice/member/controller/dto/request/MemberRequest.java index dbfa263..adde8e6 100644 --- a/src/main/java/com/cow/cow_mvc_practice/member/controller/dto/request/MemberRequest.java +++ b/src/main/java/com/cow/cow_mvc_practice/member/controller/dto/request/MemberRequest.java @@ -1,23 +1,15 @@ package com.cow.cow_mvc_practice.member.controller.dto.request; import com.cow.cow_mvc_practice.member.entity.Member; - -import lombok.AllArgsConstructor; -import lombok.Builder; import lombok.Getter; +import lombok.NoArgsConstructor; @Getter -@AllArgsConstructor +@NoArgsConstructor public class MemberRequest { - Long id; - final String name; - - @Builder - private MemberRequest(final String name) { - this.name = name; - } + private String name; - public static Member toEntity(String name) { - return Member.from(name); + public Member toEntity() { + return Member.from(this.name); } -} +} \ No newline at end of file diff --git a/src/main/java/com/cow/cow_mvc_practice/member/controller/dto/request/UpdateMemberRequest.java b/src/main/java/com/cow/cow_mvc_practice/member/controller/dto/request/UpdateMemberRequest.java index 706870d..4edd5c0 100644 --- a/src/main/java/com/cow/cow_mvc_practice/member/controller/dto/request/UpdateMemberRequest.java +++ b/src/main/java/com/cow/cow_mvc_practice/member/controller/dto/request/UpdateMemberRequest.java @@ -1,11 +1,10 @@ package com.cow.cow_mvc_practice.member.controller.dto.request; -import lombok.AllArgsConstructor; import lombok.Getter; +import lombok.NoArgsConstructor; @Getter -@AllArgsConstructor +@NoArgsConstructor public class UpdateMemberRequest { - - final String name = null; + private String name; } diff --git a/src/main/java/com/cow/cow_mvc_practice/member/service/MemberServiceImpl.java b/src/main/java/com/cow/cow_mvc_practice/member/service/MemberServiceImpl.java index 35f7565..82de7ad 100644 --- a/src/main/java/com/cow/cow_mvc_practice/member/service/MemberServiceImpl.java +++ b/src/main/java/com/cow/cow_mvc_practice/member/service/MemberServiceImpl.java @@ -20,28 +20,11 @@ @RequiredArgsConstructor @Transactional public class MemberServiceImpl implements MemberService { - private final MemberJPARepository memberRepository; - // private final MemberRepository memberRepository; - - /* 기본 */ - // @Override - // public void join(MemberRequest memberRequest) { - // Member member = Member.from(memberRequest.getId(), memberRequest.getName()); - // memberRepository.save(member); - // } - // - // @Transactional(readOnly = true) - // @Override - // public Member findOne(Long memberId) { - // return memberRepository.findById(memberId) - // .orElseThrow(() -> new EntityNotFoundException("[Error] 사용자를 찾을 수 없습니다.")); - // } - /* MemberResponse dto 적용 */ @Override public MemberResponse join(MemberRequest memberRequest) { - Member member = Member.from(memberRequest.getName()); + Member member = memberRequest.toEntity(); memberRepository.save(member); return MemberResponse.from(member); } @@ -54,6 +37,7 @@ public MemberResponse findOne(Long memberId) { return MemberResponse.from(member); } + @Transactional(readOnly = true) @Override public List findAll() { List members = memberRepository.findAll(); @@ -68,7 +52,6 @@ public String delete(Long memberId) { return "삭제에 성공하였습니다."; } - @Transactional @Override public MemberResponse updateById(Long memberId, UpdateMemberRequest updateMemberRequest) { Member member = memberRepository.findById(memberId) diff --git a/src/main/java/com/cow/cow_mvc_practice/post/controller/PostController.java b/src/main/java/com/cow/cow_mvc_practice/post/controller/PostController.java index 2e45981..0e0f0fe 100644 --- a/src/main/java/com/cow/cow_mvc_practice/post/controller/PostController.java +++ b/src/main/java/com/cow/cow_mvc_practice/post/controller/PostController.java @@ -17,16 +17,15 @@ @RequestMapping("/post") @RequiredArgsConstructor public class PostController { - private final PostService postService; - @PostMapping("/members/{memberId}/new") - public PostResponse create(@PathVariable final Long memberId ,@RequestBody final PostRequest postRequest) { + @PostMapping("/new/member/{memberId}") + public PostResponse create(@PathVariable final Long memberId, @RequestBody final PostRequest postRequest) { return postService.join(memberId, postRequest); } @GetMapping("/{postId}") - public PostResponse findMember(@PathVariable final Long postId) { + public PostResponse findPost(@PathVariable final Long postId) { return postService.findOne(postId); } @@ -35,13 +34,13 @@ public PostResponse findPostQuery(@RequestParam("id") final Long postId) { return postService.findOne(postId); } - @GetMapping("all") + @GetMapping("/all") public List findPosts() { return postService.findAll(); } - @PostMapping("/{memberId}/new") - public PostResponse create2(@PathVariable final Long memberId, @RequestBody final PostRequest postRequest) { - return postService.join(memberId, postRequest); + @GetMapping("/all/member/{memberId}") + public List findPostsByMember(@PathVariable final Long memberId) { + return postService.findAllByMember(memberId); } } diff --git a/src/main/java/com/cow/cow_mvc_practice/post/controller/dto/request/PostRequest.java b/src/main/java/com/cow/cow_mvc_practice/post/controller/dto/request/PostRequest.java index 5c6ef08..880f536 100644 --- a/src/main/java/com/cow/cow_mvc_practice/post/controller/dto/request/PostRequest.java +++ b/src/main/java/com/cow/cow_mvc_practice/post/controller/dto/request/PostRequest.java @@ -1,25 +1,11 @@ package com.cow.cow_mvc_practice.post.controller.dto.request; -import java.time.LocalDateTime; -import lombok.AllArgsConstructor; -import lombok.Builder; import lombok.Getter; +import lombok.NoArgsConstructor; @Getter -@AllArgsConstructor +@NoArgsConstructor public class PostRequest { - Long id; - final String title; - final String content; - - public PostRequest() { - this.title = ""; - this.content = ""; - } - - @Builder - private PostRequest(final String title, final String content, final LocalDateTime date) { - this.title = title; - this.content = content; - } -} + private String title; + private String content; +} \ No newline at end of file diff --git a/src/main/java/com/cow/cow_mvc_practice/post/controller/dto/request/UpdatePostRequest.java b/src/main/java/com/cow/cow_mvc_practice/post/controller/dto/request/UpdatePostRequest.java index de822bb..ed753d9 100644 --- a/src/main/java/com/cow/cow_mvc_practice/post/controller/dto/request/UpdatePostRequest.java +++ b/src/main/java/com/cow/cow_mvc_practice/post/controller/dto/request/UpdatePostRequest.java @@ -1,10 +1,13 @@ package com.cow.cow_mvc_practice.post.controller.dto.request; import com.cow.cow_mvc_practice.member.entity.Member; +import lombok.Getter; +import lombok.NoArgsConstructor; +@Getter +@NoArgsConstructor public class UpdatePostRequest { - private String title; private String content; private Member member; -} +} \ No newline at end of file diff --git a/src/main/java/com/cow/cow_mvc_practice/post/controller/dto/response/PostResponse.java b/src/main/java/com/cow/cow_mvc_practice/post/controller/dto/response/PostResponse.java index eba1b3b..e64fc28 100644 --- a/src/main/java/com/cow/cow_mvc_practice/post/controller/dto/response/PostResponse.java +++ b/src/main/java/com/cow/cow_mvc_practice/post/controller/dto/response/PostResponse.java @@ -1,8 +1,11 @@ package com.cow.cow_mvc_practice.post.controller.dto.response; +import com.cow.cow_mvc_practice.comment.entity.Comment; import com.cow.cow_mvc_practice.post.entity.Post; import com.fasterxml.jackson.annotation.JsonFormat; import java.time.LocalDateTime; +import java.util.List; +import java.util.stream.Collectors; import lombok.Builder; import lombok.Getter; @@ -17,15 +20,22 @@ public class PostResponse { private final String memberName; @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss", timezone = "Asia/Seoul") - final LocalDateTime date; + private final LocalDateTime date; + + private final int commentCount; + + private final List comments; @Builder - private PostResponse(final Long id, final String title, final String content, final String memberName, final LocalDateTime date) { + private PostResponse(final Long id, final String title, final String content, + final String memberName, final LocalDateTime date, final List comments) { this.id = id; this.title = title; this.content = content; this.memberName = memberName; this.date = date; + this.comments = comments.stream().map(Comment::getContent).collect(Collectors.toList()); + this.commentCount = this.comments.size(); } public static PostResponse from(final Post post) { @@ -35,6 +45,7 @@ public static PostResponse from(final Post post) { .content(post.getContent()) .memberName(post.getMember().getName()) .date(post.getDate()) + .comments(post.getComments()) .build(); } } diff --git a/src/main/java/com/cow/cow_mvc_practice/post/repository/PostJPARepository.java b/src/main/java/com/cow/cow_mvc_practice/post/repository/PostJPARepository.java index 662b1aa..cbbc232 100644 --- a/src/main/java/com/cow/cow_mvc_practice/post/repository/PostJPARepository.java +++ b/src/main/java/com/cow/cow_mvc_practice/post/repository/PostJPARepository.java @@ -1,6 +1,9 @@ package com.cow.cow_mvc_practice.post.repository; import com.cow.cow_mvc_practice.post.entity.Post; +import java.util.List; import org.springframework.data.jpa.repository.JpaRepository; -public interface PostJPARepository extends JpaRepository {} \ No newline at end of file +public interface PostJPARepository extends JpaRepository { + List findAllByMemberId(Long memberId); +} \ No newline at end of file diff --git a/src/main/java/com/cow/cow_mvc_practice/post/service/PostService.java b/src/main/java/com/cow/cow_mvc_practice/post/service/PostService.java index 2fbd18c..1c8b9d2 100644 --- a/src/main/java/com/cow/cow_mvc_practice/post/service/PostService.java +++ b/src/main/java/com/cow/cow_mvc_practice/post/service/PostService.java @@ -9,4 +9,5 @@ public interface PostService { PostResponse findOne(Long postId); PostResponse join(Long memberId, PostRequest postRequest); List findAll(); + List findAllByMember(Long memberId); } diff --git a/src/main/java/com/cow/cow_mvc_practice/post/service/PostServiceImpl.java b/src/main/java/com/cow/cow_mvc_practice/post/service/PostServiceImpl.java index 5f64312..48e6e8d 100644 --- a/src/main/java/com/cow/cow_mvc_practice/post/service/PostServiceImpl.java +++ b/src/main/java/com/cow/cow_mvc_practice/post/service/PostServiceImpl.java @@ -11,7 +11,6 @@ import java.util.List; import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -22,7 +21,6 @@ public class PostServiceImpl implements PostService{ private final PostJPARepository postRepository; - @Autowired private final MemberJPARepository memberRepository; @Override @@ -42,6 +40,7 @@ public PostResponse findOne(Long postId) { return PostResponse.from(post); } + @Transactional(readOnly = true) @Override public List findAll() { List posts = postRepository.findAll(); @@ -49,4 +48,13 @@ public List findAll() { .map(PostResponse::from) .collect(Collectors.toList()); } + + @Transactional(readOnly = true) + @Override + public List findAllByMember(Long memberId) { + List posts = postRepository.findAllByMemberId(memberId); + return posts.stream() + .map(PostResponse::from) + .collect(Collectors.toList()); + } } From 514a6fc0f16e33d8bf2ce86234546699efce3b50 Mon Sep 17 00:00:00 2001 From: BuildTools Date: Sat, 18 May 2024 22:17:54 +0900 Subject: [PATCH 08/18] =?UTF-8?q?style=20:=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EC=A0=95=EB=A6=AC=20=EB=B0=8F=20=EC=82=AC=EC=9A=A9=ED=95=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EB=8A=94=20=EB=A9=94=EC=84=9C=EB=93=9C=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cow_mvc_practice/CowMvcPracticeApplication.java | 1 - .../controller/dto/request/UpdateCommentRequest.java | 2 +- .../controller/dto/response/CommentResponse.java | 11 +++++++++-- .../cow/cow_mvc_practice/comment/entity/Comment.java | 1 - .../comment/repository/CommentJPARepository.java | 1 - .../comment/service/CommentService.java | 2 +- .../member/controller/MemberController.java | 2 -- .../cow/cow_mvc_practice/member/entity/Member.java | 11 +---------- .../member/repository/MemberRepository.java | 2 -- .../member/service/MemberService.java | 8 +------- .../member/service/MemberServiceImpl.java | 2 +- .../post/controller/dto/response/PostResponse.java | 4 ---- .../com/cow/cow_mvc_practice/post/entity/Post.java | 4 +--- .../cow_mvc_practice/post/service/PostService.java | 3 +-- .../post/service/PostServiceImpl.java | 2 -- 15 files changed, 16 insertions(+), 40 deletions(-) diff --git a/src/main/java/com/cow/cow_mvc_practice/CowMvcPracticeApplication.java b/src/main/java/com/cow/cow_mvc_practice/CowMvcPracticeApplication.java index 007c332..677eb51 100644 --- a/src/main/java/com/cow/cow_mvc_practice/CowMvcPracticeApplication.java +++ b/src/main/java/com/cow/cow_mvc_practice/CowMvcPracticeApplication.java @@ -9,5 +9,4 @@ public class CowMvcPracticeApplication { public static void main(String[] args) { SpringApplication.run(CowMvcPracticeApplication.class, args); } - } diff --git a/src/main/java/com/cow/cow_mvc_practice/comment/controller/dto/request/UpdateCommentRequest.java b/src/main/java/com/cow/cow_mvc_practice/comment/controller/dto/request/UpdateCommentRequest.java index 22823b3..e338398 100644 --- a/src/main/java/com/cow/cow_mvc_practice/comment/controller/dto/request/UpdateCommentRequest.java +++ b/src/main/java/com/cow/cow_mvc_practice/comment/controller/dto/request/UpdateCommentRequest.java @@ -7,4 +7,4 @@ @NoArgsConstructor public class UpdateCommentRequest { private String title; -} +} \ No newline at end of file diff --git a/src/main/java/com/cow/cow_mvc_practice/comment/controller/dto/response/CommentResponse.java b/src/main/java/com/cow/cow_mvc_practice/comment/controller/dto/response/CommentResponse.java index eda5b90..e59b463 100644 --- a/src/main/java/com/cow/cow_mvc_practice/comment/controller/dto/response/CommentResponse.java +++ b/src/main/java/com/cow/cow_mvc_practice/comment/controller/dto/response/CommentResponse.java @@ -9,17 +9,22 @@ @Getter public class CommentResponse { private final Long id; - private final String content; @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss", timezone = "Asia/Seoul") private final LocalDateTime date; + private final String postTitle; + private final String memberName; + @Builder - private CommentResponse(final Long id, final String content, final LocalDateTime date) { + private CommentResponse(final Long id, final String content, final LocalDateTime date, + final String postTitle, final String memberName) { this.id = id; this.content = content; this.date = date; + this.postTitle = postTitle; + this.memberName = memberName; } public static CommentResponse from(final Comment comment) { @@ -27,6 +32,8 @@ public static CommentResponse from(final Comment comment) { .id(comment.getId()) .content(comment.getContent()) .date(comment.getDate()) + .postTitle(comment.getPost().getTitle()) + .memberName(comment.getMember().getName()) .build(); } } \ No newline at end of file diff --git a/src/main/java/com/cow/cow_mvc_practice/comment/entity/Comment.java b/src/main/java/com/cow/cow_mvc_practice/comment/entity/Comment.java index a2d7fe5..071963c 100644 --- a/src/main/java/com/cow/cow_mvc_practice/comment/entity/Comment.java +++ b/src/main/java/com/cow/cow_mvc_practice/comment/entity/Comment.java @@ -25,7 +25,6 @@ public class Comment { @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "comment_id") private Long id; - private String content; @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss", timezone = "Asia/Seoul") diff --git a/src/main/java/com/cow/cow_mvc_practice/comment/repository/CommentJPARepository.java b/src/main/java/com/cow/cow_mvc_practice/comment/repository/CommentJPARepository.java index e774562..18e55b1 100644 --- a/src/main/java/com/cow/cow_mvc_practice/comment/repository/CommentJPARepository.java +++ b/src/main/java/com/cow/cow_mvc_practice/comment/repository/CommentJPARepository.java @@ -6,6 +6,5 @@ public interface CommentJPARepository extends JpaRepository { List findAllByMemberId(Long memberId); - List findAllByPostId(Long postId); } \ No newline at end of file diff --git a/src/main/java/com/cow/cow_mvc_practice/comment/service/CommentService.java b/src/main/java/com/cow/cow_mvc_practice/comment/service/CommentService.java index 2cb4cc0..06e1fec 100644 --- a/src/main/java/com/cow/cow_mvc_practice/comment/service/CommentService.java +++ b/src/main/java/com/cow/cow_mvc_practice/comment/service/CommentService.java @@ -10,4 +10,4 @@ public interface CommentService { List findAllByPost(Long postId); List findAllByMember(Long memberId); List findAll(); -} +} \ No newline at end of file diff --git a/src/main/java/com/cow/cow_mvc_practice/member/controller/MemberController.java b/src/main/java/com/cow/cow_mvc_practice/member/controller/MemberController.java index cedd37f..e4b3aae 100644 --- a/src/main/java/com/cow/cow_mvc_practice/member/controller/MemberController.java +++ b/src/main/java/com/cow/cow_mvc_practice/member/controller/MemberController.java @@ -23,10 +23,8 @@ @RequestMapping("/member") @RequiredArgsConstructor public class MemberController { - private final MemberService memberService; - /* MemberResponse dto 적용 */ @PostMapping("/new") public MemberResponse create(@RequestBody final MemberRequest memberRequest) { return memberService.join(memberRequest); diff --git a/src/main/java/com/cow/cow_mvc_practice/member/entity/Member.java b/src/main/java/com/cow/cow_mvc_practice/member/entity/Member.java index cd30391..2223049 100644 --- a/src/main/java/com/cow/cow_mvc_practice/member/entity/Member.java +++ b/src/main/java/com/cow/cow_mvc_practice/member/entity/Member.java @@ -22,12 +22,10 @@ @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) public class Member { - @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "member_id") private Long id; - private String name; @OneToMany(mappedBy = "member", cascade = CascadeType.ALL) @@ -48,14 +46,7 @@ public static Member from(String name) { .build(); } - public static Member of(Long id, String name) { - return Member.builder() - .id(id) - .name(name) - .build(); - } - - public void updateMember(String name) { + public void updateMemberName(String name) { this.name = name; } } diff --git a/src/main/java/com/cow/cow_mvc_practice/member/repository/MemberRepository.java b/src/main/java/com/cow/cow_mvc_practice/member/repository/MemberRepository.java index f58f4c5..675c67e 100644 --- a/src/main/java/com/cow/cow_mvc_practice/member/repository/MemberRepository.java +++ b/src/main/java/com/cow/cow_mvc_practice/member/repository/MemberRepository.java @@ -8,8 +8,6 @@ public interface MemberRepository { void save(Member member); - Optional findById(Long memberId); - Optional> findAll(); } \ No newline at end of file diff --git a/src/main/java/com/cow/cow_mvc_practice/member/service/MemberService.java b/src/main/java/com/cow/cow_mvc_practice/member/service/MemberService.java index 5feaa0b..4601cd5 100644 --- a/src/main/java/com/cow/cow_mvc_practice/member/service/MemberService.java +++ b/src/main/java/com/cow/cow_mvc_practice/member/service/MemberService.java @@ -7,15 +7,9 @@ import com.cow.cow_mvc_practice.member.controller.dto.response.MemberResponse; public interface MemberService { - - /* 기본 */ - // void join(MemberRequest memberRequest); - // Member findOne(Long memberId); - - /* MemberResponse dto 적용 */ MemberResponse findOne(Long memberId); MemberResponse join(MemberRequest memberRequest); List findAll(); String delete(Long memberId); MemberResponse updateById(Long memberId, UpdateMemberRequest updateMemberRequest); -} +} \ No newline at end of file diff --git a/src/main/java/com/cow/cow_mvc_practice/member/service/MemberServiceImpl.java b/src/main/java/com/cow/cow_mvc_practice/member/service/MemberServiceImpl.java index 82de7ad..052ea54 100644 --- a/src/main/java/com/cow/cow_mvc_practice/member/service/MemberServiceImpl.java +++ b/src/main/java/com/cow/cow_mvc_practice/member/service/MemberServiceImpl.java @@ -57,7 +57,7 @@ public MemberResponse updateById(Long memberId, UpdateMemberRequest updateMember Member member = memberRepository.findById(memberId) .orElseThrow(() -> new EntityNotFoundException("[Error] 사용자를 찾을 수 없습니다.")); String name = Optional.ofNullable(updateMemberRequest.getName()).orElse(member.getName()); - member.updateMember(name); + member.updateMemberName(name); return MemberResponse.from(member); } } \ No newline at end of file diff --git a/src/main/java/com/cow/cow_mvc_practice/post/controller/dto/response/PostResponse.java b/src/main/java/com/cow/cow_mvc_practice/post/controller/dto/response/PostResponse.java index e64fc28..96a46a7 100644 --- a/src/main/java/com/cow/cow_mvc_practice/post/controller/dto/response/PostResponse.java +++ b/src/main/java/com/cow/cow_mvc_practice/post/controller/dto/response/PostResponse.java @@ -12,18 +12,14 @@ @Getter public class PostResponse { private final Long id; - private final String title; - private final String content; - private final String memberName; @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss", timezone = "Asia/Seoul") private final LocalDateTime date; private final int commentCount; - private final List comments; @Builder diff --git a/src/main/java/com/cow/cow_mvc_practice/post/entity/Post.java b/src/main/java/com/cow/cow_mvc_practice/post/entity/Post.java index 4801eb8..b40beb9 100644 --- a/src/main/java/com/cow/cow_mvc_practice/post/entity/Post.java +++ b/src/main/java/com/cow/cow_mvc_practice/post/entity/Post.java @@ -31,9 +31,7 @@ public class Post { @Column(name = "post_id") @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - private String title; - private String content; @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss", timezone = "Asia/Seoul") @@ -43,7 +41,7 @@ public class Post { @JoinColumn(name = "member_id") private Member member; - @OneToMany(mappedBy = "post") + @OneToMany(mappedBy = "post", cascade = CascadeType.ALL) private final List comments = new ArrayList<>(); @Builder diff --git a/src/main/java/com/cow/cow_mvc_practice/post/service/PostService.java b/src/main/java/com/cow/cow_mvc_practice/post/service/PostService.java index 1c8b9d2..9bd60e8 100644 --- a/src/main/java/com/cow/cow_mvc_practice/post/service/PostService.java +++ b/src/main/java/com/cow/cow_mvc_practice/post/service/PostService.java @@ -5,9 +5,8 @@ import java.util.List; public interface PostService { - PostResponse findOne(Long postId); PostResponse join(Long memberId, PostRequest postRequest); List findAll(); List findAllByMember(Long memberId); -} +} \ No newline at end of file diff --git a/src/main/java/com/cow/cow_mvc_practice/post/service/PostServiceImpl.java b/src/main/java/com/cow/cow_mvc_practice/post/service/PostServiceImpl.java index 48e6e8d..0c13d8f 100644 --- a/src/main/java/com/cow/cow_mvc_practice/post/service/PostServiceImpl.java +++ b/src/main/java/com/cow/cow_mvc_practice/post/service/PostServiceImpl.java @@ -18,9 +18,7 @@ @RequiredArgsConstructor @Transactional public class PostServiceImpl implements PostService{ - private final PostJPARepository postRepository; - private final MemberJPARepository memberRepository; @Override From 9b6a8b0955f0213856ebed2fcbab93be6bf1dc72 Mon Sep 17 00:00:00 2001 From: BuildTools Date: Sat, 18 May 2024 23:13:43 +0900 Subject: [PATCH 09/18] =?UTF-8?q?feat=20:=20EntityNotFoundException?= =?UTF-8?q?=EC=9D=98=20=20Handler=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../member/controller/MemberController.java | 11 ++++++++++- .../member/service/MemberService.java | 3 ++- .../member/service/MemberServiceImpl.java | 10 ++++++++-- 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/cow/cow_mvc_practice/member/controller/MemberController.java b/src/main/java/com/cow/cow_mvc_practice/member/controller/MemberController.java index e4b3aae..53a4d3a 100644 --- a/src/main/java/com/cow/cow_mvc_practice/member/controller/MemberController.java +++ b/src/main/java/com/cow/cow_mvc_practice/member/controller/MemberController.java @@ -1,9 +1,13 @@ package com.cow.cow_mvc_practice.member.controller; import com.cow.cow_mvc_practice.member.controller.dto.request.UpdateMemberRequest; +import jakarta.persistence.EntityNotFoundException; import java.util.List; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PatchMapping; import org.springframework.web.bind.annotation.PathVariable; @@ -51,7 +55,12 @@ public MemberResponse update(@PathVariable final Long memberId, @RequestBody fin } @DeleteMapping("/{memberId}") - public String delete(@PathVariable final Long memberId) { + public ResponseEntity delete(@PathVariable final Long memberId) { return memberService.delete(memberId); } + + @ExceptionHandler(EntityNotFoundException.class) + public ResponseEntity handleNoSuchElementFoundException(EntityNotFoundException exception) { + return ResponseEntity.status(HttpStatus.NOT_FOUND).body(exception.getMessage()); + } } \ No newline at end of file diff --git a/src/main/java/com/cow/cow_mvc_practice/member/service/MemberService.java b/src/main/java/com/cow/cow_mvc_practice/member/service/MemberService.java index 4601cd5..77b50a1 100644 --- a/src/main/java/com/cow/cow_mvc_practice/member/service/MemberService.java +++ b/src/main/java/com/cow/cow_mvc_practice/member/service/MemberService.java @@ -5,11 +5,12 @@ import com.cow.cow_mvc_practice.member.controller.dto.request.MemberRequest; import com.cow.cow_mvc_practice.member.controller.dto.response.MemberResponse; +import org.springframework.http.ResponseEntity; public interface MemberService { MemberResponse findOne(Long memberId); MemberResponse join(MemberRequest memberRequest); List findAll(); - String delete(Long memberId); + ResponseEntity delete(Long memberId); MemberResponse updateById(Long memberId, UpdateMemberRequest updateMemberRequest); } \ No newline at end of file diff --git a/src/main/java/com/cow/cow_mvc_practice/member/service/MemberServiceImpl.java b/src/main/java/com/cow/cow_mvc_practice/member/service/MemberServiceImpl.java index 052ea54..8499022 100644 --- a/src/main/java/com/cow/cow_mvc_practice/member/service/MemberServiceImpl.java +++ b/src/main/java/com/cow/cow_mvc_practice/member/service/MemberServiceImpl.java @@ -5,6 +5,8 @@ import java.util.Optional; import java.util.stream.Collectors; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -47,9 +49,13 @@ public List findAll() { } @Override - public String delete(Long memberId) { + public ResponseEntity delete(Long memberId) { + boolean isExistMember = memberRepository.existsById(memberId); + if (!isExistMember) { + throw new EntityNotFoundException("[Error] 사용자를 찾을 수 없습니다."); + } memberRepository.deleteById(memberId); - return "삭제에 성공하였습니다."; + return new ResponseEntity<>(null, null, HttpStatus.NO_CONTENT); } @Override From 618911823462ebe4020f838ae8e4a1e5ebc40767 Mon Sep 17 00:00:00 2001 From: BuildTools Date: Sat, 18 May 2024 23:18:23 +0900 Subject: [PATCH 10/18] =?UTF-8?q?feat=20:=20=EA=B2=8C=EC=8B=9C=EA=B8=80=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../post/controller/PostController.java | 15 +++++++++++++++ .../post/service/PostService.java | 3 +++ .../post/service/PostServiceImpl.java | 12 ++++++++++++ 3 files changed, 30 insertions(+) diff --git a/src/main/java/com/cow/cow_mvc_practice/post/controller/PostController.java b/src/main/java/com/cow/cow_mvc_practice/post/controller/PostController.java index 0e0f0fe..d4e576e 100644 --- a/src/main/java/com/cow/cow_mvc_practice/post/controller/PostController.java +++ b/src/main/java/com/cow/cow_mvc_practice/post/controller/PostController.java @@ -3,8 +3,13 @@ import com.cow.cow_mvc_practice.post.controller.dto.request.PostRequest; import com.cow.cow_mvc_practice.post.controller.dto.response.PostResponse; import com.cow.cow_mvc_practice.post.service.PostService; +import jakarta.persistence.EntityNotFoundException; import java.util.List; import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; @@ -43,4 +48,14 @@ public List findPosts() { public List findPostsByMember(@PathVariable final Long memberId) { return postService.findAllByMember(memberId); } + + @DeleteMapping("/{postId}") + public ResponseEntity deletePost(@PathVariable final Long postId) { + return postService.delete(postId); + } + + @ExceptionHandler(EntityNotFoundException.class) + public ResponseEntity handleNoSuchElementFoundException(EntityNotFoundException exception) { + return ResponseEntity.status(HttpStatus.NOT_FOUND).body(exception.getMessage()); + } } diff --git a/src/main/java/com/cow/cow_mvc_practice/post/service/PostService.java b/src/main/java/com/cow/cow_mvc_practice/post/service/PostService.java index 9bd60e8..b77c370 100644 --- a/src/main/java/com/cow/cow_mvc_practice/post/service/PostService.java +++ b/src/main/java/com/cow/cow_mvc_practice/post/service/PostService.java @@ -3,10 +3,13 @@ import com.cow.cow_mvc_practice.post.controller.dto.request.PostRequest; import com.cow.cow_mvc_practice.post.controller.dto.response.PostResponse; import java.util.List; +import org.springframework.http.ResponseEntity; public interface PostService { PostResponse findOne(Long postId); PostResponse join(Long memberId, PostRequest postRequest); List findAll(); List findAllByMember(Long memberId); + + ResponseEntity delete(Long postId); } \ No newline at end of file diff --git a/src/main/java/com/cow/cow_mvc_practice/post/service/PostServiceImpl.java b/src/main/java/com/cow/cow_mvc_practice/post/service/PostServiceImpl.java index 0c13d8f..a45da7e 100644 --- a/src/main/java/com/cow/cow_mvc_practice/post/service/PostServiceImpl.java +++ b/src/main/java/com/cow/cow_mvc_practice/post/service/PostServiceImpl.java @@ -11,6 +11,8 @@ import java.util.List; import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -55,4 +57,14 @@ public List findAllByMember(Long memberId) { .map(PostResponse::from) .collect(Collectors.toList()); } + + @Override + public ResponseEntity delete(Long postId) { + boolean isExistPost = postRepository.existsById(postId); + if (!isExistPost) { + throw new EntityNotFoundException("[Error] 게시글을 찾을 수 없습니다."); + } + postRepository.deleteById(postId); + return new ResponseEntity<>(null, null, HttpStatus.NO_CONTENT); + } } From 9a01e3b9f797d3fb2cc87500ddefdfd2c21f7576 Mon Sep 17 00:00:00 2001 From: BuildTools Date: Tue, 21 May 2024 11:31:27 +0900 Subject: [PATCH 11/18] =?UTF-8?q?style=20:=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EC=BB=A8=EB=B2=A4=EC=85=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../comment/controller/CommentController.java | 51 ------------- .../dto/request/CommentRequest.java | 11 --- .../dto/response/CommentResponse.java | 39 ---------- .../comment/entity/Comment.java | 58 -------------- .../repository/CommentJPARepository.java | 10 --- .../comment/service/CommentService.java | 13 ---- .../comment/service/CommentServiceImpl.java | 72 ------------------ .../member/service/MemberService.java | 16 ---- .../post/controller/PostController.java | 61 --------------- .../controller/dto/request/PostRequest.java | 11 --- .../dto/request/UpdatePostRequest.java | 13 ---- .../controller/dto/response/PostResponse.java | 47 ------------ .../post/repository/PostRepository.java | 14 ---- .../post/repository/PostRepositoryImpl.java | 27 ------- .../post/service/PostService.java | 15 ---- .../post/service/PostServiceImpl.java | 70 ----------------- .../comment/controller/CommentController.java | 55 ++++++++++++++ .../dto/request/CommentRequest.java | 11 +++ .../dto/request/UpdateCommentRequest.java | 6 +- .../dto/response/CommentResponse.java | 41 ++++++++++ .../com/cow/mvc/comment/entity/Comment.java | 60 +++++++++++++++ .../repository/CommentJPARepository.java | 13 ++++ .../mvc/comment/service/CommentService.java | 18 +++++ .../comment/service/CommentServiceImpl.java | 75 +++++++++++++++++++ .../member/controller/MemberController.java | 19 ++--- .../controller/dto/request/MemberRequest.java | 11 ++- .../dto/request/UpdateMemberRequest.java | 2 +- .../dto/response/MemberResponse.java | 9 ++- .../member/entity/Member.java | 6 +- .../repository/MemberJPARepository.java | 7 +- .../member/repository/MemberRepository.java | 8 +- .../repository/MemberRepositoryImpl.java | 7 +- .../cow/mvc/member/service/MemberService.java | 21 ++++++ .../member/service/MemberServiceImpl.java | 16 ++-- .../mvc/post/controller/PostController.java | 64 ++++++++++++++++ .../controller/dto/request/PostRequest.java | 11 +++ .../dto/request/UpdatePostRequest.java | 14 ++++ .../controller/dto/response/PostResponse.java | 49 ++++++++++++ .../post/entity/Post.java | 16 ++-- .../post/repository/PostJPARepository.java | 10 ++- .../mvc/post/repository/PostRepository.java | 15 ++++ .../post/repository/PostRepositoryImpl.java | 28 +++++++ .../com/cow/mvc/post/service/PostService.java | 20 +++++ .../cow/mvc/post/service/PostServiceImpl.java | 73 ++++++++++++++++++ 44 files changed, 631 insertions(+), 582 deletions(-) delete mode 100644 src/main/java/com/cow/cow_mvc_practice/comment/controller/CommentController.java delete mode 100644 src/main/java/com/cow/cow_mvc_practice/comment/controller/dto/request/CommentRequest.java delete mode 100644 src/main/java/com/cow/cow_mvc_practice/comment/controller/dto/response/CommentResponse.java delete mode 100644 src/main/java/com/cow/cow_mvc_practice/comment/entity/Comment.java delete mode 100644 src/main/java/com/cow/cow_mvc_practice/comment/repository/CommentJPARepository.java delete mode 100644 src/main/java/com/cow/cow_mvc_practice/comment/service/CommentService.java delete mode 100644 src/main/java/com/cow/cow_mvc_practice/comment/service/CommentServiceImpl.java delete mode 100644 src/main/java/com/cow/cow_mvc_practice/member/service/MemberService.java delete mode 100644 src/main/java/com/cow/cow_mvc_practice/post/controller/PostController.java delete mode 100644 src/main/java/com/cow/cow_mvc_practice/post/controller/dto/request/PostRequest.java delete mode 100644 src/main/java/com/cow/cow_mvc_practice/post/controller/dto/request/UpdatePostRequest.java delete mode 100644 src/main/java/com/cow/cow_mvc_practice/post/controller/dto/response/PostResponse.java delete mode 100644 src/main/java/com/cow/cow_mvc_practice/post/repository/PostRepository.java delete mode 100644 src/main/java/com/cow/cow_mvc_practice/post/repository/PostRepositoryImpl.java delete mode 100644 src/main/java/com/cow/cow_mvc_practice/post/service/PostService.java delete mode 100644 src/main/java/com/cow/cow_mvc_practice/post/service/PostServiceImpl.java create mode 100644 src/main/java/com/cow/mvc/comment/controller/CommentController.java create mode 100644 src/main/java/com/cow/mvc/comment/controller/dto/request/CommentRequest.java rename src/main/java/com/cow/{cow_mvc_practice => mvc}/comment/controller/dto/request/UpdateCommentRequest.java (57%) create mode 100644 src/main/java/com/cow/mvc/comment/controller/dto/response/CommentResponse.java create mode 100644 src/main/java/com/cow/mvc/comment/entity/Comment.java create mode 100644 src/main/java/com/cow/mvc/comment/repository/CommentJPARepository.java create mode 100644 src/main/java/com/cow/mvc/comment/service/CommentService.java create mode 100644 src/main/java/com/cow/mvc/comment/service/CommentServiceImpl.java rename src/main/java/com/cow/{cow_mvc_practice => mvc}/member/controller/MemberController.java (83%) rename src/main/java/com/cow/{cow_mvc_practice => mvc}/member/controller/dto/request/MemberRequest.java (52%) rename src/main/java/com/cow/{cow_mvc_practice => mvc}/member/controller/dto/request/UpdateMemberRequest.java (69%) rename src/main/java/com/cow/{cow_mvc_practice => mvc}/member/controller/dto/response/MemberResponse.java (84%) rename src/main/java/com/cow/{cow_mvc_practice => mvc}/member/entity/Member.java (88%) rename src/main/java/com/cow/{cow_mvc_practice => mvc}/member/repository/MemberJPARepository.java (52%) rename src/main/java/com/cow/{cow_mvc_practice => mvc}/member/repository/MemberRepository.java (64%) rename src/main/java/com/cow/{cow_mvc_practice => mvc}/member/repository/MemberRepositoryImpl.java (87%) create mode 100644 src/main/java/com/cow/mvc/member/service/MemberService.java rename src/main/java/com/cow/{cow_mvc_practice => mvc}/member/service/MemberServiceImpl.java (78%) create mode 100644 src/main/java/com/cow/mvc/post/controller/PostController.java create mode 100644 src/main/java/com/cow/mvc/post/controller/dto/request/PostRequest.java create mode 100644 src/main/java/com/cow/mvc/post/controller/dto/request/UpdatePostRequest.java create mode 100644 src/main/java/com/cow/mvc/post/controller/dto/response/PostResponse.java rename src/main/java/com/cow/{cow_mvc_practice => mvc}/post/entity/Post.java (91%) rename src/main/java/com/cow/{cow_mvc_practice => mvc}/post/repository/PostJPARepository.java (51%) create mode 100644 src/main/java/com/cow/mvc/post/repository/PostRepository.java create mode 100644 src/main/java/com/cow/mvc/post/repository/PostRepositoryImpl.java create mode 100644 src/main/java/com/cow/mvc/post/service/PostService.java create mode 100644 src/main/java/com/cow/mvc/post/service/PostServiceImpl.java diff --git a/src/main/java/com/cow/cow_mvc_practice/comment/controller/CommentController.java b/src/main/java/com/cow/cow_mvc_practice/comment/controller/CommentController.java deleted file mode 100644 index aa90fa8..0000000 --- a/src/main/java/com/cow/cow_mvc_practice/comment/controller/CommentController.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.cow.cow_mvc_practice.comment.controller; - -import com.cow.cow_mvc_practice.comment.controller.dto.request.CommentRequest; -import com.cow.cow_mvc_practice.comment.controller.dto.response.CommentResponse; -import com.cow.cow_mvc_practice.comment.service.CommentService; -import java.util.List; -import lombok.RequiredArgsConstructor; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; - -@RestController -@RequestMapping("/comment") -@RequiredArgsConstructor -public class CommentController { - private final CommentService commentService; - - @PostMapping("/new/member/{memberId}/post/{postId}") - public CommentResponse create(@PathVariable final Long memberId, @PathVariable final Long postId, @RequestBody final CommentRequest commentRequest) { - return commentService.join(memberId, postId, commentRequest); - } - - @GetMapping("/{commentId}") - public CommentResponse findMember(@PathVariable final Long commentId) { - return commentService.findOne(commentId); - } - - @GetMapping() - public CommentResponse findCommentQuery(@RequestParam("id") final Long commentId) { - return commentService.findOne(commentId); - } - - @GetMapping("all") - public List findComments() { - return commentService.findAll(); - } - - @GetMapping("/all/member/{memberId}") - public List findCommentsByMember(@PathVariable final Long memberId) { - return commentService.findAllByMember(memberId); - } - - @GetMapping("/all/post/{postId}") - public List findCommentsByPost(@PathVariable final Long postId) { - return commentService.findAllByPost(postId); - } -} \ No newline at end of file diff --git a/src/main/java/com/cow/cow_mvc_practice/comment/controller/dto/request/CommentRequest.java b/src/main/java/com/cow/cow_mvc_practice/comment/controller/dto/request/CommentRequest.java deleted file mode 100644 index f4bf57d..0000000 --- a/src/main/java/com/cow/cow_mvc_practice/comment/controller/dto/request/CommentRequest.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.cow.cow_mvc_practice.comment.controller.dto.request; - -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Getter -@NoArgsConstructor -public class CommentRequest { - private String title; - private String content; -} \ No newline at end of file diff --git a/src/main/java/com/cow/cow_mvc_practice/comment/controller/dto/response/CommentResponse.java b/src/main/java/com/cow/cow_mvc_practice/comment/controller/dto/response/CommentResponse.java deleted file mode 100644 index e59b463..0000000 --- a/src/main/java/com/cow/cow_mvc_practice/comment/controller/dto/response/CommentResponse.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.cow.cow_mvc_practice.comment.controller.dto.response; - -import com.cow.cow_mvc_practice.comment.entity.Comment; -import com.fasterxml.jackson.annotation.JsonFormat; -import java.time.LocalDateTime; -import lombok.Builder; -import lombok.Getter; - -@Getter -public class CommentResponse { - private final Long id; - private final String content; - - @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss", timezone = "Asia/Seoul") - private final LocalDateTime date; - - private final String postTitle; - private final String memberName; - - @Builder - private CommentResponse(final Long id, final String content, final LocalDateTime date, - final String postTitle, final String memberName) { - this.id = id; - this.content = content; - this.date = date; - this.postTitle = postTitle; - this.memberName = memberName; - } - - public static CommentResponse from(final Comment comment) { - return CommentResponse.builder() - .id(comment.getId()) - .content(comment.getContent()) - .date(comment.getDate()) - .postTitle(comment.getPost().getTitle()) - .memberName(comment.getMember().getName()) - .build(); - } -} \ No newline at end of file diff --git a/src/main/java/com/cow/cow_mvc_practice/comment/entity/Comment.java b/src/main/java/com/cow/cow_mvc_practice/comment/entity/Comment.java deleted file mode 100644 index 071963c..0000000 --- a/src/main/java/com/cow/cow_mvc_practice/comment/entity/Comment.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.cow.cow_mvc_practice.comment.entity; - -import com.cow.cow_mvc_practice.member.entity.Member; -import com.cow.cow_mvc_practice.post.entity.Post; -import com.fasterxml.jackson.annotation.JsonFormat; -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.FetchType; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import jakarta.persistence.JoinColumn; -import jakarta.persistence.ManyToOne; -import java.time.LocalDateTime; -import lombok.AccessLevel; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Entity -@Getter -@NoArgsConstructor(access = AccessLevel.PROTECTED) -public class Comment { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "comment_id") - private Long id; - private String content; - - @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss", timezone = "Asia/Seoul") - private LocalDateTime date; - - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "post_id") - private Post post; - - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "member_id") - private Member member; - - @Builder - private Comment(final Long id, final String content, final LocalDateTime date, Post post, Member member) { - this.id = id; - this.content = content; - this.date = date; - this.post = post; - this.member = member; - } - - public static Comment of(String content, LocalDateTime date, Post post, Member member) { - return Comment.builder() - .content(content) - .date(date) - .post(post) - .member(member) - .build(); - } -} \ No newline at end of file diff --git a/src/main/java/com/cow/cow_mvc_practice/comment/repository/CommentJPARepository.java b/src/main/java/com/cow/cow_mvc_practice/comment/repository/CommentJPARepository.java deleted file mode 100644 index 18e55b1..0000000 --- a/src/main/java/com/cow/cow_mvc_practice/comment/repository/CommentJPARepository.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.cow.cow_mvc_practice.comment.repository; - -import com.cow.cow_mvc_practice.comment.entity.Comment; -import java.util.List; -import org.springframework.data.jpa.repository.JpaRepository; - -public interface CommentJPARepository extends JpaRepository { - List findAllByMemberId(Long memberId); - List findAllByPostId(Long postId); -} \ No newline at end of file diff --git a/src/main/java/com/cow/cow_mvc_practice/comment/service/CommentService.java b/src/main/java/com/cow/cow_mvc_practice/comment/service/CommentService.java deleted file mode 100644 index 06e1fec..0000000 --- a/src/main/java/com/cow/cow_mvc_practice/comment/service/CommentService.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.cow.cow_mvc_practice.comment.service; - -import com.cow.cow_mvc_practice.comment.controller.dto.request.CommentRequest; -import com.cow.cow_mvc_practice.comment.controller.dto.response.CommentResponse; -import java.util.List; - -public interface CommentService { - CommentResponse findOne(Long commentId); - CommentResponse join(Long memberId, Long postId, CommentRequest commentRequest); - List findAllByPost(Long postId); - List findAllByMember(Long memberId); - List findAll(); -} \ No newline at end of file diff --git a/src/main/java/com/cow/cow_mvc_practice/comment/service/CommentServiceImpl.java b/src/main/java/com/cow/cow_mvc_practice/comment/service/CommentServiceImpl.java deleted file mode 100644 index db587b1..0000000 --- a/src/main/java/com/cow/cow_mvc_practice/comment/service/CommentServiceImpl.java +++ /dev/null @@ -1,72 +0,0 @@ -package com.cow.cow_mvc_practice.comment.service; - -import com.cow.cow_mvc_practice.comment.controller.dto.request.CommentRequest; -import com.cow.cow_mvc_practice.comment.controller.dto.response.CommentResponse; -import com.cow.cow_mvc_practice.comment.entity.Comment; -import com.cow.cow_mvc_practice.comment.repository.CommentJPARepository; -import com.cow.cow_mvc_practice.member.entity.Member; -import com.cow.cow_mvc_practice.member.repository.MemberJPARepository; -import com.cow.cow_mvc_practice.post.entity.Post; -import com.cow.cow_mvc_practice.post.repository.PostJPARepository; -import jakarta.persistence.EntityNotFoundException; -import java.time.LocalDateTime; -import java.util.List; -import java.util.stream.Collectors; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -@Service -@RequiredArgsConstructor -@Transactional -public class CommentServiceImpl implements CommentService { - private final CommentJPARepository commentRepository; - private final MemberJPARepository memberRepository; - private final PostJPARepository postRepository; - - @Transactional(readOnly = true) - @Override - public CommentResponse findOne(Long commentId) { - Comment comment = commentRepository.findById(commentId) - .orElseThrow(() -> new EntityNotFoundException("[Error] 댓글을 찾을 수 없습니다.")); - return CommentResponse.from(comment); - } - - @Override - public CommentResponse join(Long memberId, Long postId, CommentRequest commentRequest) { - Member member = this.memberRepository.findById(memberId) - .orElseThrow(() -> new EntityNotFoundException("[Error] 사용자를 찾을 수 없습니다.")); - Post post = this.postRepository.findById(postId) - .orElseThrow(() -> new EntityNotFoundException("[Error] 게시글을 찾을 수 없습니다.")); - Comment comment = Comment.of(commentRequest.getContent(), LocalDateTime.now(), post, member); - commentRepository.save(comment); - return CommentResponse.from(comment); - } - - @Transactional(readOnly = true) - @Override - public List findAllByPost(Long postId) { - List comments = commentRepository.findAllByPostId(postId); - return comments.stream() - .map(CommentResponse::from) - .collect(Collectors.toList()); - } - - @Transactional(readOnly = true) - @Override - public List findAllByMember(Long memberId) { - List comments = commentRepository.findAllByMemberId(memberId); - return comments.stream() - .map(CommentResponse::from) - .collect(Collectors.toList()); - } - - @Transactional(readOnly = true) - @Override - public List findAll() { - List comments = commentRepository.findAll(); - return comments.stream() - .map(CommentResponse::from) - .collect(Collectors.toList()); - } -} diff --git a/src/main/java/com/cow/cow_mvc_practice/member/service/MemberService.java b/src/main/java/com/cow/cow_mvc_practice/member/service/MemberService.java deleted file mode 100644 index 77b50a1..0000000 --- a/src/main/java/com/cow/cow_mvc_practice/member/service/MemberService.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.cow.cow_mvc_practice.member.service; - -import com.cow.cow_mvc_practice.member.controller.dto.request.UpdateMemberRequest; -import java.util.List; - -import com.cow.cow_mvc_practice.member.controller.dto.request.MemberRequest; -import com.cow.cow_mvc_practice.member.controller.dto.response.MemberResponse; -import org.springframework.http.ResponseEntity; - -public interface MemberService { - MemberResponse findOne(Long memberId); - MemberResponse join(MemberRequest memberRequest); - List findAll(); - ResponseEntity delete(Long memberId); - MemberResponse updateById(Long memberId, UpdateMemberRequest updateMemberRequest); -} \ No newline at end of file diff --git a/src/main/java/com/cow/cow_mvc_practice/post/controller/PostController.java b/src/main/java/com/cow/cow_mvc_practice/post/controller/PostController.java deleted file mode 100644 index d4e576e..0000000 --- a/src/main/java/com/cow/cow_mvc_practice/post/controller/PostController.java +++ /dev/null @@ -1,61 +0,0 @@ -package com.cow.cow_mvc_practice.post.controller; - -import com.cow.cow_mvc_practice.post.controller.dto.request.PostRequest; -import com.cow.cow_mvc_practice.post.controller.dto.response.PostResponse; -import com.cow.cow_mvc_practice.post.service.PostService; -import jakarta.persistence.EntityNotFoundException; -import java.util.List; -import lombok.RequiredArgsConstructor; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.ExceptionHandler; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; - -@RestController -@RequestMapping("/post") -@RequiredArgsConstructor -public class PostController { - private final PostService postService; - - @PostMapping("/new/member/{memberId}") - public PostResponse create(@PathVariable final Long memberId, @RequestBody final PostRequest postRequest) { - return postService.join(memberId, postRequest); - } - - @GetMapping("/{postId}") - public PostResponse findPost(@PathVariable final Long postId) { - return postService.findOne(postId); - } - - @GetMapping() - public PostResponse findPostQuery(@RequestParam("id") final Long postId) { - return postService.findOne(postId); - } - - @GetMapping("/all") - public List findPosts() { - return postService.findAll(); - } - - @GetMapping("/all/member/{memberId}") - public List findPostsByMember(@PathVariable final Long memberId) { - return postService.findAllByMember(memberId); - } - - @DeleteMapping("/{postId}") - public ResponseEntity deletePost(@PathVariable final Long postId) { - return postService.delete(postId); - } - - @ExceptionHandler(EntityNotFoundException.class) - public ResponseEntity handleNoSuchElementFoundException(EntityNotFoundException exception) { - return ResponseEntity.status(HttpStatus.NOT_FOUND).body(exception.getMessage()); - } -} diff --git a/src/main/java/com/cow/cow_mvc_practice/post/controller/dto/request/PostRequest.java b/src/main/java/com/cow/cow_mvc_practice/post/controller/dto/request/PostRequest.java deleted file mode 100644 index 880f536..0000000 --- a/src/main/java/com/cow/cow_mvc_practice/post/controller/dto/request/PostRequest.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.cow.cow_mvc_practice.post.controller.dto.request; - -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Getter -@NoArgsConstructor -public class PostRequest { - private String title; - private String content; -} \ No newline at end of file diff --git a/src/main/java/com/cow/cow_mvc_practice/post/controller/dto/request/UpdatePostRequest.java b/src/main/java/com/cow/cow_mvc_practice/post/controller/dto/request/UpdatePostRequest.java deleted file mode 100644 index ed753d9..0000000 --- a/src/main/java/com/cow/cow_mvc_practice/post/controller/dto/request/UpdatePostRequest.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.cow.cow_mvc_practice.post.controller.dto.request; - -import com.cow.cow_mvc_practice.member.entity.Member; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Getter -@NoArgsConstructor -public class UpdatePostRequest { - private String title; - private String content; - private Member member; -} \ No newline at end of file diff --git a/src/main/java/com/cow/cow_mvc_practice/post/controller/dto/response/PostResponse.java b/src/main/java/com/cow/cow_mvc_practice/post/controller/dto/response/PostResponse.java deleted file mode 100644 index 96a46a7..0000000 --- a/src/main/java/com/cow/cow_mvc_practice/post/controller/dto/response/PostResponse.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.cow.cow_mvc_practice.post.controller.dto.response; - -import com.cow.cow_mvc_practice.comment.entity.Comment; -import com.cow.cow_mvc_practice.post.entity.Post; -import com.fasterxml.jackson.annotation.JsonFormat; -import java.time.LocalDateTime; -import java.util.List; -import java.util.stream.Collectors; -import lombok.Builder; -import lombok.Getter; - -@Getter -public class PostResponse { - private final Long id; - private final String title; - private final String content; - private final String memberName; - - @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss", timezone = "Asia/Seoul") - private final LocalDateTime date; - - private final int commentCount; - private final List comments; - - @Builder - private PostResponse(final Long id, final String title, final String content, - final String memberName, final LocalDateTime date, final List comments) { - this.id = id; - this.title = title; - this.content = content; - this.memberName = memberName; - this.date = date; - this.comments = comments.stream().map(Comment::getContent).collect(Collectors.toList()); - this.commentCount = this.comments.size(); - } - - public static PostResponse from(final Post post) { - return PostResponse.builder() - .id(post.getId()) - .title(post.getTitle()) - .content(post.getContent()) - .memberName(post.getMember().getName()) - .date(post.getDate()) - .comments(post.getComments()) - .build(); - } -} diff --git a/src/main/java/com/cow/cow_mvc_practice/post/repository/PostRepository.java b/src/main/java/com/cow/cow_mvc_practice/post/repository/PostRepository.java deleted file mode 100644 index bf26ef9..0000000 --- a/src/main/java/com/cow/cow_mvc_practice/post/repository/PostRepository.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.cow.cow_mvc_practice.post.repository; - -import com.cow.cow_mvc_practice.post.entity.Post; -import java.util.List; -import java.util.Optional; - -public interface PostRepository { - - void save(Post post); - - Optional findById(Long postId); - - Optional> findAll(); -} \ No newline at end of file diff --git a/src/main/java/com/cow/cow_mvc_practice/post/repository/PostRepositoryImpl.java b/src/main/java/com/cow/cow_mvc_practice/post/repository/PostRepositoryImpl.java deleted file mode 100644 index 47ffce4..0000000 --- a/src/main/java/com/cow/cow_mvc_practice/post/repository/PostRepositoryImpl.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.cow.cow_mvc_practice.post.repository; - -import com.cow.cow_mvc_practice.post.entity.Post; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; - -public class PostRepositoryImpl implements PostRepository{ - - private static final Map store = new HashMap<>(); - - @Override - public void save(Post post) { - store.put(post.getId(), post); - } - - @Override - public Optional findById(Long memberId) { - return Optional.ofNullable(store.get(memberId)); - } - - @Override - public Optional> findAll() { - return Optional.of((List)store.values()); - } -} diff --git a/src/main/java/com/cow/cow_mvc_practice/post/service/PostService.java b/src/main/java/com/cow/cow_mvc_practice/post/service/PostService.java deleted file mode 100644 index b77c370..0000000 --- a/src/main/java/com/cow/cow_mvc_practice/post/service/PostService.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.cow.cow_mvc_practice.post.service; - -import com.cow.cow_mvc_practice.post.controller.dto.request.PostRequest; -import com.cow.cow_mvc_practice.post.controller.dto.response.PostResponse; -import java.util.List; -import org.springframework.http.ResponseEntity; - -public interface PostService { - PostResponse findOne(Long postId); - PostResponse join(Long memberId, PostRequest postRequest); - List findAll(); - List findAllByMember(Long memberId); - - ResponseEntity delete(Long postId); -} \ No newline at end of file diff --git a/src/main/java/com/cow/cow_mvc_practice/post/service/PostServiceImpl.java b/src/main/java/com/cow/cow_mvc_practice/post/service/PostServiceImpl.java deleted file mode 100644 index a45da7e..0000000 --- a/src/main/java/com/cow/cow_mvc_practice/post/service/PostServiceImpl.java +++ /dev/null @@ -1,70 +0,0 @@ -package com.cow.cow_mvc_practice.post.service; - -import com.cow.cow_mvc_practice.member.entity.Member; -import com.cow.cow_mvc_practice.member.repository.MemberJPARepository; -import com.cow.cow_mvc_practice.post.controller.dto.request.PostRequest; -import com.cow.cow_mvc_practice.post.controller.dto.response.PostResponse; -import com.cow.cow_mvc_practice.post.entity.Post; -import com.cow.cow_mvc_practice.post.repository.PostJPARepository; -import jakarta.persistence.EntityNotFoundException; -import java.time.LocalDateTime; -import java.util.List; -import java.util.stream.Collectors; -import lombok.RequiredArgsConstructor; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -@Service -@RequiredArgsConstructor -@Transactional -public class PostServiceImpl implements PostService{ - private final PostJPARepository postRepository; - private final MemberJPARepository memberRepository; - - @Override - public PostResponse join(Long memberId, PostRequest postRequest) { - Member member = memberRepository.findById(memberId) - .orElseThrow(() -> new EntityNotFoundException("[Error] 사용자를 찾을 수 없습니다.")); - Post post = Post.of(postRequest.getTitle(), postRequest.getContent(), member, LocalDateTime.now()); - postRepository.save(post); - return PostResponse.from(post); - } - - @Transactional(readOnly = true) - @Override - public PostResponse findOne(Long postId) { - Post post = postRepository.findById(postId) - .orElseThrow(() -> new EntityNotFoundException("[Error] 게시글을 찾을 수 없습니다.")); - return PostResponse.from(post); - } - - @Transactional(readOnly = true) - @Override - public List findAll() { - List posts = postRepository.findAll(); - return posts.stream() - .map(PostResponse::from) - .collect(Collectors.toList()); - } - - @Transactional(readOnly = true) - @Override - public List findAllByMember(Long memberId) { - List posts = postRepository.findAllByMemberId(memberId); - return posts.stream() - .map(PostResponse::from) - .collect(Collectors.toList()); - } - - @Override - public ResponseEntity delete(Long postId) { - boolean isExistPost = postRepository.existsById(postId); - if (!isExistPost) { - throw new EntityNotFoundException("[Error] 게시글을 찾을 수 없습니다."); - } - postRepository.deleteById(postId); - return new ResponseEntity<>(null, null, HttpStatus.NO_CONTENT); - } -} diff --git a/src/main/java/com/cow/mvc/comment/controller/CommentController.java b/src/main/java/com/cow/mvc/comment/controller/CommentController.java new file mode 100644 index 0000000..b77be57 --- /dev/null +++ b/src/main/java/com/cow/mvc/comment/controller/CommentController.java @@ -0,0 +1,55 @@ +package com.cow.mvc.comment.controller; + +import java.util.List; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import com.cow.mvc.comment.controller.dto.request.CommentRequest; +import com.cow.mvc.comment.controller.dto.response.CommentResponse; +import com.cow.mvc.comment.service.CommentService; + +import lombok.RequiredArgsConstructor; + +@RestController +@RequestMapping("/comment") +@RequiredArgsConstructor +public class CommentController { + private final CommentService commentService; + + @PostMapping("/new/member/{memberId}/post/{postId}") + public CommentResponse create(@PathVariable final Long memberId, @PathVariable final Long postId, + @RequestBody final CommentRequest commentRequest) { + return commentService.join(memberId, postId, commentRequest); + } + + @GetMapping("/{commentId}") + public CommentResponse findMember(@PathVariable final Long commentId) { + return commentService.findOne(commentId); + } + + @GetMapping() + public CommentResponse findCommentQuery(@RequestParam("id") final Long commentId) { + return commentService.findOne(commentId); + } + + @GetMapping("all") + public List findComments() { + return commentService.findAll(); + } + + @GetMapping("/all/member/{memberId}") + public List findCommentsByMember(@PathVariable final Long memberId) { + return commentService.findAllByMember(memberId); + } + + @GetMapping("/all/post/{postId}") + public List findCommentsByPost(@PathVariable final Long postId) { + return commentService.findAllByPost(postId); + } +} diff --git a/src/main/java/com/cow/mvc/comment/controller/dto/request/CommentRequest.java b/src/main/java/com/cow/mvc/comment/controller/dto/request/CommentRequest.java new file mode 100644 index 0000000..5f0b703 --- /dev/null +++ b/src/main/java/com/cow/mvc/comment/controller/dto/request/CommentRequest.java @@ -0,0 +1,11 @@ +package com.cow.mvc.comment.controller.dto.request; + +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +public class CommentRequest { + private String title; + private String content; +} diff --git a/src/main/java/com/cow/cow_mvc_practice/comment/controller/dto/request/UpdateCommentRequest.java b/src/main/java/com/cow/mvc/comment/controller/dto/request/UpdateCommentRequest.java similarity index 57% rename from src/main/java/com/cow/cow_mvc_practice/comment/controller/dto/request/UpdateCommentRequest.java rename to src/main/java/com/cow/mvc/comment/controller/dto/request/UpdateCommentRequest.java index e338398..2269cf8 100644 --- a/src/main/java/com/cow/cow_mvc_practice/comment/controller/dto/request/UpdateCommentRequest.java +++ b/src/main/java/com/cow/mvc/comment/controller/dto/request/UpdateCommentRequest.java @@ -1,4 +1,4 @@ -package com.cow.cow_mvc_practice.comment.controller.dto.request; +package com.cow.mvc.comment.controller.dto.request; import lombok.Getter; import lombok.NoArgsConstructor; @@ -6,5 +6,5 @@ @Getter @NoArgsConstructor public class UpdateCommentRequest { - private String title; -} \ No newline at end of file + private String title; +} diff --git a/src/main/java/com/cow/mvc/comment/controller/dto/response/CommentResponse.java b/src/main/java/com/cow/mvc/comment/controller/dto/response/CommentResponse.java new file mode 100644 index 0000000..3deb41b --- /dev/null +++ b/src/main/java/com/cow/mvc/comment/controller/dto/response/CommentResponse.java @@ -0,0 +1,41 @@ +package com.cow.mvc.comment.controller.dto.response; + +import java.time.LocalDateTime; + +import com.cow.mvc.comment.entity.Comment; +import com.fasterxml.jackson.annotation.JsonFormat; + +import lombok.Builder; +import lombok.Getter; + +@Getter +public class CommentResponse { + private final Long id; + private final String content; + + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss", timezone = "Asia/Seoul") + private final LocalDateTime date; + + private final String postTitle; + private final String memberName; + + @Builder + private CommentResponse(final Long id, final String content, final LocalDateTime date, + final String postTitle, final String memberName) { + this.id = id; + this.content = content; + this.date = date; + this.postTitle = postTitle; + this.memberName = memberName; + } + + public static CommentResponse from(final Comment comment) { + return CommentResponse.builder() + .id(comment.getId()) + .content(comment.getContent()) + .date(comment.getDate()) + .postTitle(comment.getPost().getTitle()) + .memberName(comment.getMember().getName()) + .build(); + } +} diff --git a/src/main/java/com/cow/mvc/comment/entity/Comment.java b/src/main/java/com/cow/mvc/comment/entity/Comment.java new file mode 100644 index 0000000..1031843 --- /dev/null +++ b/src/main/java/com/cow/mvc/comment/entity/Comment.java @@ -0,0 +1,60 @@ +package com.cow.mvc.comment.entity; + +import java.time.LocalDateTime; + +import com.cow.mvc.member.entity.Member; +import com.cow.mvc.post.entity.Post; +import com.fasterxml.jackson.annotation.JsonFormat; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +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; + +@Entity +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class Comment { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "comment_id") + private Long id; + private String content; + + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss", timezone = "Asia/Seoul") + private LocalDateTime date; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "post_id") + private Post post; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "member_id") + private Member member; + + @Builder + private Comment(final Long id, final String content, final LocalDateTime date, Post post, Member member) { + this.id = id; + this.content = content; + this.date = date; + this.post = post; + this.member = member; + } + + public static Comment of(String content, LocalDateTime date, Post post, Member member) { + return Comment.builder() + .content(content) + .date(date) + .post(post) + .member(member) + .build(); + } +} diff --git a/src/main/java/com/cow/mvc/comment/repository/CommentJPARepository.java b/src/main/java/com/cow/mvc/comment/repository/CommentJPARepository.java new file mode 100644 index 0000000..baa2b7d --- /dev/null +++ b/src/main/java/com/cow/mvc/comment/repository/CommentJPARepository.java @@ -0,0 +1,13 @@ +package com.cow.mvc.comment.repository; + +import java.util.List; + +import org.springframework.data.jpa.repository.JpaRepository; + +import com.cow.mvc.comment.entity.Comment; + +public interface CommentJPARepository extends JpaRepository { + List findAllByMemberId(Long memberId); + + List findAllByPostId(Long postId); +} diff --git a/src/main/java/com/cow/mvc/comment/service/CommentService.java b/src/main/java/com/cow/mvc/comment/service/CommentService.java new file mode 100644 index 0000000..81bc189 --- /dev/null +++ b/src/main/java/com/cow/mvc/comment/service/CommentService.java @@ -0,0 +1,18 @@ +package com.cow.mvc.comment.service; + +import java.util.List; + +import com.cow.mvc.comment.controller.dto.request.CommentRequest; +import com.cow.mvc.comment.controller.dto.response.CommentResponse; + +public interface CommentService { + CommentResponse findOne(Long commentId); + + CommentResponse join(Long memberId, Long postId, CommentRequest commentRequest); + + List findAllByPost(Long postId); + + List findAllByMember(Long memberId); + + List findAll(); +} diff --git a/src/main/java/com/cow/mvc/comment/service/CommentServiceImpl.java b/src/main/java/com/cow/mvc/comment/service/CommentServiceImpl.java new file mode 100644 index 0000000..9e8aa7c --- /dev/null +++ b/src/main/java/com/cow/mvc/comment/service/CommentServiceImpl.java @@ -0,0 +1,75 @@ +package com.cow.mvc.comment.service; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.stream.Collectors; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.cow.mvc.comment.controller.dto.request.CommentRequest; +import com.cow.mvc.comment.controller.dto.response.CommentResponse; +import com.cow.mvc.comment.entity.Comment; +import com.cow.mvc.comment.repository.CommentJPARepository; +import com.cow.mvc.member.entity.Member; +import com.cow.mvc.member.repository.MemberJPARepository; +import com.cow.mvc.post.entity.Post; +import com.cow.mvc.post.repository.PostJPARepository; + +import jakarta.persistence.EntityNotFoundException; +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +@Transactional +public class CommentServiceImpl implements CommentService { + private final CommentJPARepository commentRepository; + private final MemberJPARepository memberRepository; + private final PostJPARepository postRepository; + + @Transactional(readOnly = true) + @Override + public CommentResponse findOne(Long commentId) { + Comment comment = commentRepository.findById(commentId) + .orElseThrow(() -> new EntityNotFoundException("[Error] 댓글을 찾을 수 없습니다.")); + return CommentResponse.from(comment); + } + + @Override + public CommentResponse join(Long memberId, Long postId, CommentRequest commentRequest) { + Member member = this.memberRepository.findById(memberId) + .orElseThrow(() -> new EntityNotFoundException("[Error] 사용자를 찾을 수 없습니다.")); + Post post = this.postRepository.findById(postId) + .orElseThrow(() -> new EntityNotFoundException("[Error] 게시글을 찾을 수 없습니다.")); + Comment comment = Comment.of(commentRequest.getContent(), LocalDateTime.now(), post, member); + commentRepository.save(comment); + return CommentResponse.from(comment); + } + + @Transactional(readOnly = true) + @Override + public List findAllByPost(Long postId) { + List comments = commentRepository.findAllByPostId(postId); + return comments.stream() + .map(CommentResponse::from) + .collect(Collectors.toList()); + } + + @Transactional(readOnly = true) + @Override + public List findAllByMember(Long memberId) { + List comments = commentRepository.findAllByMemberId(memberId); + return comments.stream() + .map(CommentResponse::from) + .collect(Collectors.toList()); + } + + @Transactional(readOnly = true) + @Override + public List findAll() { + List comments = commentRepository.findAll(); + return comments.stream() + .map(CommentResponse::from) + .collect(Collectors.toList()); + } +} diff --git a/src/main/java/com/cow/cow_mvc_practice/member/controller/MemberController.java b/src/main/java/com/cow/mvc/member/controller/MemberController.java similarity index 83% rename from src/main/java/com/cow/cow_mvc_practice/member/controller/MemberController.java rename to src/main/java/com/cow/mvc/member/controller/MemberController.java index 53a4d3a..69915ff 100644 --- a/src/main/java/com/cow/cow_mvc_practice/member/controller/MemberController.java +++ b/src/main/java/com/cow/mvc/member/controller/MemberController.java @@ -1,7 +1,5 @@ -package com.cow.cow_mvc_practice.member.controller; +package com.cow.mvc.member.controller; -import com.cow.cow_mvc_practice.member.controller.dto.request.UpdateMemberRequest; -import jakarta.persistence.EntityNotFoundException; import java.util.List; import org.springframework.http.HttpStatus; @@ -15,13 +13,15 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; -import com.cow.cow_mvc_practice.member.controller.dto.request.MemberRequest; -import com.cow.cow_mvc_practice.member.controller.dto.response.MemberResponse; -import com.cow.cow_mvc_practice.member.service.MemberService; +import com.cow.mvc.member.controller.dto.request.MemberRequest; +import com.cow.mvc.member.controller.dto.request.UpdateMemberRequest; +import com.cow.mvc.member.controller.dto.response.MemberResponse; +import com.cow.mvc.member.service.MemberService; +import jakarta.persistence.EntityNotFoundException; import lombok.RequiredArgsConstructor; -import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/member") @@ -50,7 +50,8 @@ public List findMembers() { } @PatchMapping(value = "/{memberId}") - public MemberResponse update(@PathVariable final Long memberId, @RequestBody final UpdateMemberRequest updateMemberRequest) { + public MemberResponse update(@PathVariable final Long memberId, + @RequestBody final UpdateMemberRequest updateMemberRequest) { return memberService.updateById(memberId, updateMemberRequest); } @@ -63,4 +64,4 @@ public ResponseEntity delete(@PathVariable final Long memberId) { public ResponseEntity handleNoSuchElementFoundException(EntityNotFoundException exception) { return ResponseEntity.status(HttpStatus.NOT_FOUND).body(exception.getMessage()); } -} \ No newline at end of file +} diff --git a/src/main/java/com/cow/cow_mvc_practice/member/controller/dto/request/MemberRequest.java b/src/main/java/com/cow/mvc/member/controller/dto/request/MemberRequest.java similarity index 52% rename from src/main/java/com/cow/cow_mvc_practice/member/controller/dto/request/MemberRequest.java rename to src/main/java/com/cow/mvc/member/controller/dto/request/MemberRequest.java index adde8e6..d741431 100644 --- a/src/main/java/com/cow/cow_mvc_practice/member/controller/dto/request/MemberRequest.java +++ b/src/main/java/com/cow/mvc/member/controller/dto/request/MemberRequest.java @@ -1,6 +1,7 @@ -package com.cow.cow_mvc_practice.member.controller.dto.request; +package com.cow.mvc.member.controller.dto.request; + +import com.cow.mvc.member.entity.Member; -import com.cow.cow_mvc_practice.member.entity.Member; import lombok.Getter; import lombok.NoArgsConstructor; @@ -10,6 +11,8 @@ public class MemberRequest { private String name; public Member toEntity() { - return Member.from(this.name); + return Member.builder() + .name(this.name) + .build(); } -} \ No newline at end of file +} diff --git a/src/main/java/com/cow/cow_mvc_practice/member/controller/dto/request/UpdateMemberRequest.java b/src/main/java/com/cow/mvc/member/controller/dto/request/UpdateMemberRequest.java similarity index 69% rename from src/main/java/com/cow/cow_mvc_practice/member/controller/dto/request/UpdateMemberRequest.java rename to src/main/java/com/cow/mvc/member/controller/dto/request/UpdateMemberRequest.java index 4edd5c0..ea30fc9 100644 --- a/src/main/java/com/cow/cow_mvc_practice/member/controller/dto/request/UpdateMemberRequest.java +++ b/src/main/java/com/cow/mvc/member/controller/dto/request/UpdateMemberRequest.java @@ -1,4 +1,4 @@ -package com.cow.cow_mvc_practice.member.controller.dto.request; +package com.cow.mvc.member.controller.dto.request; import lombok.Getter; import lombok.NoArgsConstructor; diff --git a/src/main/java/com/cow/cow_mvc_practice/member/controller/dto/response/MemberResponse.java b/src/main/java/com/cow/mvc/member/controller/dto/response/MemberResponse.java similarity index 84% rename from src/main/java/com/cow/cow_mvc_practice/member/controller/dto/response/MemberResponse.java rename to src/main/java/com/cow/mvc/member/controller/dto/response/MemberResponse.java index ca35f5c..5740969 100644 --- a/src/main/java/com/cow/cow_mvc_practice/member/controller/dto/response/MemberResponse.java +++ b/src/main/java/com/cow/mvc/member/controller/dto/response/MemberResponse.java @@ -1,9 +1,10 @@ -package com.cow.cow_mvc_practice.member.controller.dto.response; - -import com.cow.cow_mvc_practice.member.entity.Member; +package com.cow.mvc.member.controller.dto.response; import java.util.ArrayList; import java.util.List; + +import com.cow.mvc.member.entity.Member; + import lombok.Builder; import lombok.Getter; @@ -29,4 +30,4 @@ public static MemberResponse from(final Member member) { .posts(posts) .build(); } -} \ No newline at end of file +} diff --git a/src/main/java/com/cow/cow_mvc_practice/member/entity/Member.java b/src/main/java/com/cow/mvc/member/entity/Member.java similarity index 88% rename from src/main/java/com/cow/cow_mvc_practice/member/entity/Member.java rename to src/main/java/com/cow/mvc/member/entity/Member.java index 2223049..2d417c2 100644 --- a/src/main/java/com/cow/cow_mvc_practice/member/entity/Member.java +++ b/src/main/java/com/cow/mvc/member/entity/Member.java @@ -1,10 +1,10 @@ -package com.cow.cow_mvc_practice.member.entity; +package com.cow.mvc.member.entity; -import com.cow.cow_mvc_practice.comment.entity.Comment; import java.util.ArrayList; import java.util.List; -import com.cow.cow_mvc_practice.post.entity.Post; +import com.cow.mvc.comment.entity.Comment; +import com.cow.mvc.post.entity.Post; import jakarta.persistence.CascadeType; import jakarta.persistence.Column; diff --git a/src/main/java/com/cow/cow_mvc_practice/member/repository/MemberJPARepository.java b/src/main/java/com/cow/mvc/member/repository/MemberJPARepository.java similarity index 52% rename from src/main/java/com/cow/cow_mvc_practice/member/repository/MemberJPARepository.java rename to src/main/java/com/cow/mvc/member/repository/MemberJPARepository.java index 4cd3fab..fc72fe7 100644 --- a/src/main/java/com/cow/cow_mvc_practice/member/repository/MemberJPARepository.java +++ b/src/main/java/com/cow/mvc/member/repository/MemberJPARepository.java @@ -1,7 +1,8 @@ -package com.cow.cow_mvc_practice.member.repository; +package com.cow.mvc.member.repository; import org.springframework.data.jpa.repository.JpaRepository; -import com.cow.cow_mvc_practice.member.entity.Member; +import com.cow.mvc.member.entity.Member; -public interface MemberJPARepository extends JpaRepository {} +public interface MemberJPARepository extends JpaRepository { +} diff --git a/src/main/java/com/cow/cow_mvc_practice/member/repository/MemberRepository.java b/src/main/java/com/cow/mvc/member/repository/MemberRepository.java similarity index 64% rename from src/main/java/com/cow/cow_mvc_practice/member/repository/MemberRepository.java rename to src/main/java/com/cow/mvc/member/repository/MemberRepository.java index 675c67e..18d8c31 100644 --- a/src/main/java/com/cow/cow_mvc_practice/member/repository/MemberRepository.java +++ b/src/main/java/com/cow/mvc/member/repository/MemberRepository.java @@ -1,13 +1,15 @@ -package com.cow.cow_mvc_practice.member.repository; +package com.cow.mvc.member.repository; import java.util.List; import java.util.Optional; -import com.cow.cow_mvc_practice.member.entity.Member; +import com.cow.mvc.member.entity.Member; public interface MemberRepository { void save(Member member); + Optional findById(Long memberId); + Optional> findAll(); -} \ No newline at end of file +} diff --git a/src/main/java/com/cow/cow_mvc_practice/member/repository/MemberRepositoryImpl.java b/src/main/java/com/cow/mvc/member/repository/MemberRepositoryImpl.java similarity index 87% rename from src/main/java/com/cow/cow_mvc_practice/member/repository/MemberRepositoryImpl.java rename to src/main/java/com/cow/mvc/member/repository/MemberRepositoryImpl.java index 29fdffc..b4ba846 100644 --- a/src/main/java/com/cow/cow_mvc_practice/member/repository/MemberRepositoryImpl.java +++ b/src/main/java/com/cow/mvc/member/repository/MemberRepositoryImpl.java @@ -1,4 +1,4 @@ -package com.cow.cow_mvc_practice.member.repository; +package com.cow.mvc.member.repository; import java.util.HashMap; import java.util.List; @@ -7,16 +7,15 @@ import org.springframework.stereotype.Repository; -import com.cow.cow_mvc_practice.member.entity.Member; +import com.cow.mvc.member.entity.Member; @Repository public class MemberRepositoryImpl implements MemberRepository { /** * 원래라면 HashMap이 아닌, concurrentHashMap이 적합함. HashMap은 멀티 쓰레드 환경에서 사용할 수 없기 때문.(동시성 이슈) - */ + */ private static final Map store = new HashMap<>(); - @Override public void save(Member member) { store.put(member.getId(), member); diff --git a/src/main/java/com/cow/mvc/member/service/MemberService.java b/src/main/java/com/cow/mvc/member/service/MemberService.java new file mode 100644 index 0000000..1a793b8 --- /dev/null +++ b/src/main/java/com/cow/mvc/member/service/MemberService.java @@ -0,0 +1,21 @@ +package com.cow.mvc.member.service; + +import java.util.List; + +import org.springframework.http.ResponseEntity; + +import com.cow.mvc.member.controller.dto.request.MemberRequest; +import com.cow.mvc.member.controller.dto.request.UpdateMemberRequest; +import com.cow.mvc.member.controller.dto.response.MemberResponse; + +public interface MemberService { + MemberResponse findOne(Long memberId); + + MemberResponse join(MemberRequest memberRequest); + + List findAll(); + + ResponseEntity delete(Long memberId); + + MemberResponse updateById(Long memberId, UpdateMemberRequest updateMemberRequest); +} diff --git a/src/main/java/com/cow/cow_mvc_practice/member/service/MemberServiceImpl.java b/src/main/java/com/cow/mvc/member/service/MemberServiceImpl.java similarity index 78% rename from src/main/java/com/cow/cow_mvc_practice/member/service/MemberServiceImpl.java rename to src/main/java/com/cow/mvc/member/service/MemberServiceImpl.java index 8499022..4e4283b 100644 --- a/src/main/java/com/cow/cow_mvc_practice/member/service/MemberServiceImpl.java +++ b/src/main/java/com/cow/mvc/member/service/MemberServiceImpl.java @@ -1,6 +1,5 @@ -package com.cow.cow_mvc_practice.member.service; +package com.cow.mvc.member.service; -import com.cow.cow_mvc_practice.member.controller.dto.request.UpdateMemberRequest; import java.util.List; import java.util.Optional; import java.util.stream.Collectors; @@ -10,10 +9,11 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import com.cow.cow_mvc_practice.member.controller.dto.request.MemberRequest; -import com.cow.cow_mvc_practice.member.controller.dto.response.MemberResponse; -import com.cow.cow_mvc_practice.member.entity.Member; -import com.cow.cow_mvc_practice.member.repository.MemberJPARepository; +import com.cow.mvc.member.controller.dto.request.MemberRequest; +import com.cow.mvc.member.controller.dto.request.UpdateMemberRequest; +import com.cow.mvc.member.controller.dto.response.MemberResponse; +import com.cow.mvc.member.entity.Member; +import com.cow.mvc.member.repository.MemberJPARepository; import jakarta.persistence.EntityNotFoundException; import lombok.RequiredArgsConstructor; @@ -61,9 +61,9 @@ public ResponseEntity delete(Long memberId) { @Override public MemberResponse updateById(Long memberId, UpdateMemberRequest updateMemberRequest) { Member member = memberRepository.findById(memberId) - .orElseThrow(() -> new EntityNotFoundException("[Error] 사용자를 찾을 수 없습니다.")); + .orElseThrow(() -> new EntityNotFoundException("[Error] 사용자를 찾을 수 없습니다.")); String name = Optional.ofNullable(updateMemberRequest.getName()).orElse(member.getName()); member.updateMemberName(name); return MemberResponse.from(member); } -} \ No newline at end of file +} diff --git a/src/main/java/com/cow/mvc/post/controller/PostController.java b/src/main/java/com/cow/mvc/post/controller/PostController.java new file mode 100644 index 0000000..f7bc4a3 --- /dev/null +++ b/src/main/java/com/cow/mvc/post/controller/PostController.java @@ -0,0 +1,64 @@ +package com.cow.mvc.post.controller; + +import java.util.List; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import com.cow.mvc.post.controller.dto.request.PostRequest; +import com.cow.mvc.post.controller.dto.response.PostResponse; +import com.cow.mvc.post.service.PostService; + +import jakarta.persistence.EntityNotFoundException; +import lombok.RequiredArgsConstructor; + +@RestController +@RequestMapping("/post") +@RequiredArgsConstructor +public class PostController { + private final PostService postService; + + @PostMapping("/new/member/{memberId}") + public PostResponse create(@PathVariable final Long memberId, @RequestBody final PostRequest postRequest) { + return postService.join(memberId, postRequest); + } + + @GetMapping("/{postId}") + public PostResponse findPost(@PathVariable final Long postId) { + return postService.findOne(postId); + } + + @GetMapping() + public PostResponse findPostQuery(@RequestParam("id") final Long postId) { + return postService.findOne(postId); + } + + @GetMapping("/all") + public List findPosts() { + return postService.findAll(); + } + + @GetMapping("/all/member/{memberId}") + public List findPostsByMember(@PathVariable final Long memberId) { + return postService.findAllByMember(memberId); + } + + @DeleteMapping("/{postId}") + public ResponseEntity deletePost(@PathVariable final Long postId) { + return postService.delete(postId); + } + + @ExceptionHandler(EntityNotFoundException.class) + public ResponseEntity handleNoSuchElementFoundException(EntityNotFoundException exception) { + return ResponseEntity.status(HttpStatus.NOT_FOUND).body(exception.getMessage()); + } +} diff --git a/src/main/java/com/cow/mvc/post/controller/dto/request/PostRequest.java b/src/main/java/com/cow/mvc/post/controller/dto/request/PostRequest.java new file mode 100644 index 0000000..9053092 --- /dev/null +++ b/src/main/java/com/cow/mvc/post/controller/dto/request/PostRequest.java @@ -0,0 +1,11 @@ +package com.cow.mvc.post.controller.dto.request; + +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +public class PostRequest { + private String title; + private String content; +} diff --git a/src/main/java/com/cow/mvc/post/controller/dto/request/UpdatePostRequest.java b/src/main/java/com/cow/mvc/post/controller/dto/request/UpdatePostRequest.java new file mode 100644 index 0000000..a2e87b7 --- /dev/null +++ b/src/main/java/com/cow/mvc/post/controller/dto/request/UpdatePostRequest.java @@ -0,0 +1,14 @@ +package com.cow.mvc.post.controller.dto.request; + +import com.cow.mvc.member.entity.Member; + +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +public class UpdatePostRequest { + private String title; + private String content; + private Member member; +} diff --git a/src/main/java/com/cow/mvc/post/controller/dto/response/PostResponse.java b/src/main/java/com/cow/mvc/post/controller/dto/response/PostResponse.java new file mode 100644 index 0000000..33fc3f1 --- /dev/null +++ b/src/main/java/com/cow/mvc/post/controller/dto/response/PostResponse.java @@ -0,0 +1,49 @@ +package com.cow.mvc.post.controller.dto.response; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.stream.Collectors; + +import com.cow.mvc.comment.entity.Comment; +import com.cow.mvc.post.entity.Post; +import com.fasterxml.jackson.annotation.JsonFormat; + +import lombok.Builder; +import lombok.Getter; + +@Getter +public class PostResponse { + private final Long id; + private final String title; + private final String content; + private final String memberName; + + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss", timezone = "Asia/Seoul") + private final LocalDateTime date; + + private final int commentCount; + private final List comments; + + @Builder + private PostResponse(final Long id, final String title, final String content, + final String memberName, final LocalDateTime date, final List comments) { + this.id = id; + this.title = title; + this.content = content; + this.memberName = memberName; + this.date = date; + this.comments = comments.stream().map(Comment::getContent).collect(Collectors.toList()); + this.commentCount = this.comments.size(); + } + + public static PostResponse from(final Post post) { + return PostResponse.builder() + .id(post.getId()) + .title(post.getTitle()) + .content(post.getContent()) + .memberName(post.getMember().getName()) + .date(post.getDate()) + .comments(post.getComments()) + .build(); + } +} diff --git a/src/main/java/com/cow/cow_mvc_practice/post/entity/Post.java b/src/main/java/com/cow/mvc/post/entity/Post.java similarity index 91% rename from src/main/java/com/cow/cow_mvc_practice/post/entity/Post.java rename to src/main/java/com/cow/mvc/post/entity/Post.java index b40beb9..d61ec3b 100644 --- a/src/main/java/com/cow/cow_mvc_practice/post/entity/Post.java +++ b/src/main/java/com/cow/mvc/post/entity/Post.java @@ -1,10 +1,13 @@ -package com.cow.cow_mvc_practice.post.entity; - -import com.cow.cow_mvc_practice.comment.entity.Comment; -import com.cow.cow_mvc_practice.member.entity.Member; +package com.cow.mvc.post.entity; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import com.cow.mvc.comment.entity.Comment; +import com.cow.mvc.member.entity.Member; import com.fasterxml.jackson.annotation.JsonFormat; + import jakarta.persistence.CascadeType; import jakarta.persistence.Column; import jakarta.persistence.Entity; @@ -15,9 +18,6 @@ import jakarta.persistence.JoinColumn; import jakarta.persistence.ManyToOne; import jakarta.persistence.OneToMany; -import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.List; import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; @@ -60,4 +60,4 @@ public static Post of(final String title, final String content, final Member mem .date(date) .build(); } -} \ No newline at end of file +} diff --git a/src/main/java/com/cow/cow_mvc_practice/post/repository/PostJPARepository.java b/src/main/java/com/cow/mvc/post/repository/PostJPARepository.java similarity index 51% rename from src/main/java/com/cow/cow_mvc_practice/post/repository/PostJPARepository.java rename to src/main/java/com/cow/mvc/post/repository/PostJPARepository.java index cbbc232..472aa1e 100644 --- a/src/main/java/com/cow/cow_mvc_practice/post/repository/PostJPARepository.java +++ b/src/main/java/com/cow/mvc/post/repository/PostJPARepository.java @@ -1,9 +1,11 @@ -package com.cow.cow_mvc_practice.post.repository; +package com.cow.mvc.post.repository; -import com.cow.cow_mvc_practice.post.entity.Post; import java.util.List; + import org.springframework.data.jpa.repository.JpaRepository; +import com.cow.mvc.post.entity.Post; + public interface PostJPARepository extends JpaRepository { - List findAllByMemberId(Long memberId); -} \ No newline at end of file + List findAllByMemberId(Long memberId); +} diff --git a/src/main/java/com/cow/mvc/post/repository/PostRepository.java b/src/main/java/com/cow/mvc/post/repository/PostRepository.java new file mode 100644 index 0000000..7cfe581 --- /dev/null +++ b/src/main/java/com/cow/mvc/post/repository/PostRepository.java @@ -0,0 +1,15 @@ +package com.cow.mvc.post.repository; + +import java.util.List; +import java.util.Optional; + +import com.cow.mvc.post.entity.Post; + +public interface PostRepository { + + void save(Post post); + + Optional findById(Long postId); + + Optional> findAll(); +} diff --git a/src/main/java/com/cow/mvc/post/repository/PostRepositoryImpl.java b/src/main/java/com/cow/mvc/post/repository/PostRepositoryImpl.java new file mode 100644 index 0000000..e132e57 --- /dev/null +++ b/src/main/java/com/cow/mvc/post/repository/PostRepositoryImpl.java @@ -0,0 +1,28 @@ +package com.cow.mvc.post.repository; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +import com.cow.mvc.post.entity.Post; + +public class PostRepositoryImpl implements PostRepository { + + private static final Map store = new HashMap<>(); + + @Override + public void save(Post post) { + store.put(post.getId(), post); + } + + @Override + public Optional findById(Long memberId) { + return Optional.ofNullable(store.get(memberId)); + } + + @Override + public Optional> findAll() { + return Optional.of((List)store.values()); + } +} diff --git a/src/main/java/com/cow/mvc/post/service/PostService.java b/src/main/java/com/cow/mvc/post/service/PostService.java new file mode 100644 index 0000000..5c21832 --- /dev/null +++ b/src/main/java/com/cow/mvc/post/service/PostService.java @@ -0,0 +1,20 @@ +package com.cow.mvc.post.service; + +import java.util.List; + +import org.springframework.http.ResponseEntity; + +import com.cow.mvc.post.controller.dto.request.PostRequest; +import com.cow.mvc.post.controller.dto.response.PostResponse; + +public interface PostService { + PostResponse findOne(Long postId); + + PostResponse join(Long memberId, PostRequest postRequest); + + List findAll(); + + List findAllByMember(Long memberId); + + ResponseEntity delete(Long postId); +} diff --git a/src/main/java/com/cow/mvc/post/service/PostServiceImpl.java b/src/main/java/com/cow/mvc/post/service/PostServiceImpl.java new file mode 100644 index 0000000..0cbf650 --- /dev/null +++ b/src/main/java/com/cow/mvc/post/service/PostServiceImpl.java @@ -0,0 +1,73 @@ +package com.cow.mvc.post.service; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.stream.Collectors; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.cow.mvc.member.entity.Member; +import com.cow.mvc.member.repository.MemberJPARepository; +import com.cow.mvc.post.controller.dto.request.PostRequest; +import com.cow.mvc.post.controller.dto.response.PostResponse; +import com.cow.mvc.post.entity.Post; +import com.cow.mvc.post.repository.PostJPARepository; + +import jakarta.persistence.EntityNotFoundException; +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +@Transactional +public class PostServiceImpl implements PostService { + private final PostJPARepository postRepository; + private final MemberJPARepository memberRepository; + + @Override + public PostResponse join(Long memberId, PostRequest postRequest) { + Member member = memberRepository.findById(memberId) + .orElseThrow(() -> new EntityNotFoundException("[Error] 사용자를 찾을 수 없습니다.")); + Post post = Post.of(postRequest.getTitle(), postRequest.getContent(), member, LocalDateTime.now()); + postRepository.save(post); + return PostResponse.from(post); + } + + @Transactional(readOnly = true) + @Override + public PostResponse findOne(Long postId) { + Post post = postRepository.findById(postId) + .orElseThrow(() -> new EntityNotFoundException("[Error] 게시글을 찾을 수 없습니다.")); + return PostResponse.from(post); + } + + @Transactional(readOnly = true) + @Override + public List findAll() { + List posts = postRepository.findAll(); + return posts.stream() + .map(PostResponse::from) + .collect(Collectors.toList()); + } + + @Transactional(readOnly = true) + @Override + public List findAllByMember(Long memberId) { + List posts = postRepository.findAllByMemberId(memberId); + return posts.stream() + .map(PostResponse::from) + .collect(Collectors.toList()); + } + + @Override + public ResponseEntity delete(Long postId) { + boolean isExistPost = postRepository.existsById(postId); + if (!isExistPost) { + throw new EntityNotFoundException("[Error] 게시글을 찾을 수 없습니다."); + } + postRepository.deleteById(postId); + return new ResponseEntity<>(null, null, HttpStatus.NO_CONTENT); + } +} From ec67ae0986bb0c4b046a9f23f160cde1cc0a3f05 Mon Sep 17 00:00:00 2001 From: BuildTools Date: Tue, 21 May 2024 11:31:27 +0900 Subject: [PATCH 12/18] =?UTF-8?q?style=20:=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EC=BB=A8=EB=B2=A4=EC=85=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 24 +++++++---- build.gradle | 42 +++++++++---------- .../CowMvcPracticeApplication.java | 2 +- 3 files changed, 37 insertions(+), 31 deletions(-) rename src/main/java/com/cow/{cow_mvc_practice => mvc}/CowMvcPracticeApplication.java (89%) diff --git a/README.md b/README.md index 85157d5..51a8e18 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ # COW MVC PRACTICE 초기 코드 ## 📮 미션 제출 방법 + - 미션 구현을 완료한 후 GitHub을 통해 제출해야 한다. - 해당 리포지토리를 fork/clone - 미션 구현 @@ -12,11 +13,13 @@ - 미션 구현 pr 링크 첨부 ## 환경 + ### [spring initializr link](https://start.spring.io/#!type=gradle-project&language=java&platformVersion=3.2.5&packaging=jar&jvmVersion=17&groupId=com.cow&artifactId=cow_mvc_practice&name=cow_mvc_practice&description=cow_mvc_practice&packageName=com.cow.cow_mvc_practice&dependencies=web,data-jpa,lombok,docker-compose) ## docker 실행 방법 -1. 프로젝트 build 후, 터미널에 `docker build` 를 해당 프로젝트 경로로 입력한다. - - ex) ~/Desktop/mju/cow/cow_mvc_practice docker build + +1. 프로젝트 build 후, 터미널에 `docker build` 를 해당 프로젝트 경로로 입력한다. + - ex) ~/Desktop/mju/cow/cow_mvc_practice docker build 2. 시작 시에는 `docker compose up` 을 입력한다. - ex) ~/Desktop/mju/cow/cow_mvc_practice docker compose up 3. 종료 시에는 `docker compose down` 을 입력한다. @@ -32,7 +35,8 @@ > 필요한 api를 직접 작성하는 능력을 키우고자, 큰 가이드 라인을 드리지 않았습니다. ### 요구사항 -1. 사용자는 사용자의 정보를 수정할 수 있습니다. (keyword: 변경감지) + +1. 사용자는 사용자의 정보를 수정할 수 있습니다. (keyword: 변경감지) 2. 실제 Member의 id값은 로그인을 통해 토큰의 값을 해석해 가져오거나, 세션 id를 통해 가져오나, 이번 미션에서는 members/1 과 같이 Path Variable을 사용해주세요. 3. Comment Entity를 생성해주세요. Comment Entity는 게시글과 1 : N, Member와 1 : N의 관계를 가지고 있습니다. (기존 코드를 참고해주세요) 3. 사용자는 특정 게시글을 조회할 수 있습니다. 이때 posts/1 와 같이 Path Variable을 통해 조회해주세요. @@ -40,17 +44,19 @@ 이때 게시글 제목, 게시글 내용, 게시글 작성자, 작성일시, 댓글 내용을 반환합니다. 4. 사용자는 게시글을 작성할 수 있습니다. Post를 생성하기 위한 정보는 body를 사용해주세요. - - 사용자는 제목과 내용을 입력해 게시글을 생성합니다. members/1와 같이 Path Variable을 사용해주세요. + - 사용자는 제목과 내용을 입력해 게시글을 생성합니다. members/1와 같이 Path Variable을 사용해주세요. -5. 사용자는 댓글을 작성할 수 있습니다. 이때 members/2/posts/1 와 같은 Path Variable를 사용하고, comment의 내용은 body를 통해 전달하는 것으로 합니다. 이때 게시글에 댓글이 작성된다면 해당 게시글의 댓글 개수를 추가하는 메서드를 작성해주세요. +5. 사용자는 댓글을 작성할 수 있습니다. 이때 members/2/posts/1 와 같은 Path Variable를 사용하고, comment의 내용은 body를 통해 전달하는 것으로 합니다. 이때 게시글에 댓글이 + 작성된다면 해당 게시글의 댓글 개수를 추가하는 메서드를 작성해주세요. 6. 사용자는 모든 게시글들을 조회할 수 있습니다. 게시글의 id, 게시글의 제목, 작성자의 이름, 게시글의 댓글 개수를 리스트로 반환합니다. -7. 사용자는 게시글을 삭제할 수 있습니다. 이때 cascade 옵션을 사용해 해당 게시글의 댓글도 같이 삭제합니다. cascade 옵션에 대해 학습하기 위해서 다음과 같은 링크를 참고해주세요. 또한 cascade 옵션이 있을 경우와 cascade 있을 경우 쿼리를 비교해서 캡쳐해주세요. +7. 사용자는 게시글을 삭제할 수 있습니다. 이때 cascade 옵션을 사용해 해당 게시글의 댓글도 같이 삭제합니다. cascade 옵션에 대해 학습하기 위해서 다음과 같은 링크를 참고해주세요. 또한 cascade + 옵션이 있을 경우와 cascade 있을 경우 쿼리를 비교해서 캡쳐해주세요. [https://velog.io/@max9106/JPA엔티티-상태-Cascade](https://velog.io/@max9106/JPA%EC%97%94%ED%8B%B0%ED%8B%B0-%EC%83%81%ED%83%9C-Cascade) --- -분명 척척해내시는 분들도 계실거고, 조금은 버거우신 분들도 존재하리라 생각이 듭니다! +분명 척척해내시는 분들도 계실거고, 조금은 버거우신 분들도 존재하리라 생각이 듭니다! 모든 것을 처음부터 잘하는 사람은 없으니 저희 멘토들에게 많은 질문해주시고 욕심이 있으신분들은 추가적인 공부를 통해 더욱더 성장하시길 바랍니다!! -모든 요구사항을 충족시키시기 어렵다는 생각이 드신다면 member, post만이라고 확실하게 구현해보시고 이해하시길 추천드려요! -또한 해당 과제에서는 간단한 mvc 구현이 목적이기에 JPA에 대한 설명이 많이 부족합니다. 너무 JPA에 대해 많은 시간을 쏟지 않으셔도 된다는 말씀드립니다. \ No newline at end of file +모든 요구사항을 충족시키시기 어렵다는 생각이 드신다면 member, post만이라고 확실하게 구현해보시고 이해하시길 추천드려요! +또한 해당 과제에서는 간단한 mvc 구현이 목적이기에 JPA에 대한 설명이 많이 부족합니다. 너무 JPA에 대해 많은 시간을 쏟지 않으셔도 된다는 말씀드립니다. diff --git a/build.gradle b/build.gradle index 403537f..b3bb126 100644 --- a/build.gradle +++ b/build.gradle @@ -1,41 +1,41 @@ plugins { - id 'java' - id 'org.springframework.boot' version '3.2.5' - id 'io.spring.dependency-management' version '1.1.4' + id 'java' + id 'org.springframework.boot' version '3.2.5' + id 'io.spring.dependency-management' version '1.1.4' } group = 'com.cow' version = '0.0.1-SNAPSHOT' java { - sourceCompatibility = '17' + sourceCompatibility = '17' } configurations { - compileOnly { - extendsFrom annotationProcessor - } + compileOnly { + extendsFrom annotationProcessor + } } repositories { - mavenCentral() + mavenCentral() } dependencies { - implementation 'mysql:mysql-connector-java:8.0.32' - implementation 'org.springframework.boot:spring-boot-starter-data-jpa' - implementation 'org.springframework.boot:spring-boot-starter-web' - testImplementation 'junit:junit:4.13.1' - compileOnly 'org.projectlombok:lombok' - developmentOnly 'org.springframework.boot:spring-boot-docker-compose' - annotationProcessor 'org.projectlombok:lombok' - testImplementation 'org.springframework.boot:spring-boot-starter-test' - testImplementation 'org.testcontainers:testcontainers' - testImplementation 'org.testcontainers:junit-jupiter:1.19.7' // Using the same version as Testcontainers - testImplementation "org.testcontainers:mysql:1.19.7" // Using the same version as Testcontainers - testImplementation 'org.testcontainers:jdbc:1.19.7' // Using the same version as Testcontainers + implementation 'mysql:mysql-connector-java:8.0.32' + implementation 'org.springframework.boot:spring-boot-starter-data-jpa' + implementation 'org.springframework.boot:spring-boot-starter-web' + testImplementation 'junit:junit:4.13.1' + compileOnly 'org.projectlombok:lombok' + developmentOnly 'org.springframework.boot:spring-boot-docker-compose' + annotationProcessor 'org.projectlombok:lombok' + testImplementation 'org.springframework.boot:spring-boot-starter-test' + testImplementation 'org.testcontainers:testcontainers' + testImplementation 'org.testcontainers:junit-jupiter:1.19.7' // Using the same version as Testcontainers + testImplementation "org.testcontainers:mysql:1.19.7" // Using the same version as Testcontainers + testImplementation 'org.testcontainers:jdbc:1.19.7' // Using the same version as Testcontainers } tasks.named('test') { - useJUnitPlatform() + useJUnitPlatform() } diff --git a/src/main/java/com/cow/cow_mvc_practice/CowMvcPracticeApplication.java b/src/main/java/com/cow/mvc/CowMvcPracticeApplication.java similarity index 89% rename from src/main/java/com/cow/cow_mvc_practice/CowMvcPracticeApplication.java rename to src/main/java/com/cow/mvc/CowMvcPracticeApplication.java index 677eb51..6373d4c 100644 --- a/src/main/java/com/cow/cow_mvc_practice/CowMvcPracticeApplication.java +++ b/src/main/java/com/cow/mvc/CowMvcPracticeApplication.java @@ -1,4 +1,4 @@ -package com.cow.cow_mvc_practice; +package com.cow.mvc; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; From 5be2e3b3814942e62c039531b86538a0d6e02d7c Mon Sep 17 00:00:00 2001 From: BuildTools Date: Tue, 21 May 2024 12:29:22 +0900 Subject: [PATCH 13/18] =?UTF-8?q?style=20:=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EC=BB=A8=EB=B2=A4=EC=85=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../comment/controller/CommentController.java | 55 ++++++++++++++ .../dto/request/CommentRequest.java | 11 +++ .../dto/response/CommentResponse.java | 41 ++++++++++ .../comment/entity/Comment.java | 60 +++++++++++++++ .../repository/CommentJPARepository.java | 13 ++++ .../comment/service/CommentService.java | 18 +++++ .../comment/service/CommentServiceImpl.java | 75 +++++++++++++++++++ .../member/service/MemberService.java | 21 ++++++ .../post/controller/PostController.java | 64 ++++++++++++++++ .../controller/dto/request/PostRequest.java | 11 +++ .../dto/request/UpdatePostRequest.java | 14 ++++ .../controller/dto/response/PostResponse.java | 49 ++++++++++++ .../post/repository/PostRepository.java | 15 ++++ .../post/repository/PostRepositoryImpl.java | 28 +++++++ .../post/service/PostService.java | 20 +++++ .../post/service/PostServiceImpl.java | 73 ++++++++++++++++++ .../member/controller/MemberController.java | 10 +-- .../controller/dto/request/MemberRequest.java | 8 +- .../dto/response/MemberResponse.java | 4 +- .../com/cow/mvc/member/entity/Member.java | 6 +- .../mvc/member/service/MemberServiceImpl.java | 12 +-- .../java/com/cow/mvc/post/entity/Post.java | 6 +- .../post/repository/PostJPARepository.java | 4 +- src/main/resources/application.yml | 2 +- 24 files changed, 593 insertions(+), 27 deletions(-) create mode 100644 src/main/java/com/cow/cow_mvc_practice/comment/controller/CommentController.java create mode 100644 src/main/java/com/cow/cow_mvc_practice/comment/controller/dto/request/CommentRequest.java create mode 100644 src/main/java/com/cow/cow_mvc_practice/comment/controller/dto/response/CommentResponse.java create mode 100644 src/main/java/com/cow/cow_mvc_practice/comment/entity/Comment.java create mode 100644 src/main/java/com/cow/cow_mvc_practice/comment/repository/CommentJPARepository.java create mode 100644 src/main/java/com/cow/cow_mvc_practice/comment/service/CommentService.java create mode 100644 src/main/java/com/cow/cow_mvc_practice/comment/service/CommentServiceImpl.java create mode 100644 src/main/java/com/cow/cow_mvc_practice/member/service/MemberService.java create mode 100644 src/main/java/com/cow/cow_mvc_practice/post/controller/PostController.java create mode 100644 src/main/java/com/cow/cow_mvc_practice/post/controller/dto/request/PostRequest.java create mode 100644 src/main/java/com/cow/cow_mvc_practice/post/controller/dto/request/UpdatePostRequest.java create mode 100644 src/main/java/com/cow/cow_mvc_practice/post/controller/dto/response/PostResponse.java create mode 100644 src/main/java/com/cow/cow_mvc_practice/post/repository/PostRepository.java create mode 100644 src/main/java/com/cow/cow_mvc_practice/post/repository/PostRepositoryImpl.java create mode 100644 src/main/java/com/cow/cow_mvc_practice/post/service/PostService.java create mode 100644 src/main/java/com/cow/cow_mvc_practice/post/service/PostServiceImpl.java diff --git a/src/main/java/com/cow/cow_mvc_practice/comment/controller/CommentController.java b/src/main/java/com/cow/cow_mvc_practice/comment/controller/CommentController.java new file mode 100644 index 0000000..b255c95 --- /dev/null +++ b/src/main/java/com/cow/cow_mvc_practice/comment/controller/CommentController.java @@ -0,0 +1,55 @@ +package com.cow.cow_mvc_practice.comment.controller; + +import java.util.List; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import com.cow.cow_mvc_practice.comment.controller.dto.request.CommentRequest; +import com.cow.cow_mvc_practice.comment.controller.dto.response.CommentResponse; +import com.cow.cow_mvc_practice.comment.service.CommentService; + +import lombok.RequiredArgsConstructor; + +@RestController +@RequestMapping("/comment") +@RequiredArgsConstructor +public class CommentController { + private final CommentService commentService; + + @PostMapping("/new/member/{memberId}/post/{postId}") + public CommentResponse create(@PathVariable final Long memberId, @PathVariable final Long postId, + @RequestBody final CommentRequest commentRequest) { + return commentService.join(memberId, postId, commentRequest); + } + + @GetMapping("/{commentId}") + public CommentResponse findMember(@PathVariable final Long commentId) { + return commentService.findOne(commentId); + } + + @GetMapping() + public CommentResponse findCommentQuery(@RequestParam("id") final Long commentId) { + return commentService.findOne(commentId); + } + + @GetMapping("all") + public List findComments() { + return commentService.findAll(); + } + + @GetMapping("/all/member/{memberId}") + public List findCommentsByMember(@PathVariable final Long memberId) { + return commentService.findAllByMember(memberId); + } + + @GetMapping("/all/post/{postId}") + public List findCommentsByPost(@PathVariable final Long postId) { + return commentService.findAllByPost(postId); + } +} diff --git a/src/main/java/com/cow/cow_mvc_practice/comment/controller/dto/request/CommentRequest.java b/src/main/java/com/cow/cow_mvc_practice/comment/controller/dto/request/CommentRequest.java new file mode 100644 index 0000000..98849a2 --- /dev/null +++ b/src/main/java/com/cow/cow_mvc_practice/comment/controller/dto/request/CommentRequest.java @@ -0,0 +1,11 @@ +package com.cow.cow_mvc_practice.comment.controller.dto.request; + +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +public class CommentRequest { + private String title; + private String content; +} diff --git a/src/main/java/com/cow/cow_mvc_practice/comment/controller/dto/response/CommentResponse.java b/src/main/java/com/cow/cow_mvc_practice/comment/controller/dto/response/CommentResponse.java new file mode 100644 index 0000000..02e2274 --- /dev/null +++ b/src/main/java/com/cow/cow_mvc_practice/comment/controller/dto/response/CommentResponse.java @@ -0,0 +1,41 @@ +package com.cow.cow_mvc_practice.comment.controller.dto.response; + +import java.time.LocalDateTime; + +import com.cow.cow_mvc_practice.comment.entity.Comment; +import com.fasterxml.jackson.annotation.JsonFormat; + +import lombok.Builder; +import lombok.Getter; + +@Getter +public class CommentResponse { + private final Long id; + private final String content; + + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss", timezone = "Asia/Seoul") + private final LocalDateTime date; + + private final String postTitle; + private final String memberName; + + @Builder + private CommentResponse(final Long id, final String content, final LocalDateTime date, + final String postTitle, final String memberName) { + this.id = id; + this.content = content; + this.date = date; + this.postTitle = postTitle; + this.memberName = memberName; + } + + public static CommentResponse from(final Comment comment) { + return CommentResponse.builder() + .id(comment.getId()) + .content(comment.getContent()) + .date(comment.getDate()) + .postTitle(comment.getPost().getTitle()) + .memberName(comment.getMember().getName()) + .build(); + } +} diff --git a/src/main/java/com/cow/cow_mvc_practice/comment/entity/Comment.java b/src/main/java/com/cow/cow_mvc_practice/comment/entity/Comment.java new file mode 100644 index 0000000..f21e6a8 --- /dev/null +++ b/src/main/java/com/cow/cow_mvc_practice/comment/entity/Comment.java @@ -0,0 +1,60 @@ +package com.cow.cow_mvc_practice.comment.entity; + +import java.time.LocalDateTime; + +import com.cow.cow_mvc_practice.member.entity.Member; +import com.cow.cow_mvc_practice.post.entity.Post; +import com.fasterxml.jackson.annotation.JsonFormat; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +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; + +@Entity +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class Comment { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "comment_id") + private Long id; + private String content; + + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss", timezone = "Asia/Seoul") + private LocalDateTime date; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "post_id") + private Post post; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "member_id") + private Member member; + + @Builder + private Comment(final Long id, final String content, final LocalDateTime date, Post post, Member member) { + this.id = id; + this.content = content; + this.date = date; + this.post = post; + this.member = member; + } + + public static Comment of(String content, LocalDateTime date, Post post, Member member) { + return Comment.builder() + .content(content) + .date(date) + .post(post) + .member(member) + .build(); + } +} diff --git a/src/main/java/com/cow/cow_mvc_practice/comment/repository/CommentJPARepository.java b/src/main/java/com/cow/cow_mvc_practice/comment/repository/CommentJPARepository.java new file mode 100644 index 0000000..1aafbac --- /dev/null +++ b/src/main/java/com/cow/cow_mvc_practice/comment/repository/CommentJPARepository.java @@ -0,0 +1,13 @@ +package com.cow.cow_mvc_practice.comment.repository; + +import java.util.List; + +import org.springframework.data.jpa.repository.JpaRepository; + +import com.cow.cow_mvc_practice.comment.entity.Comment; + +public interface CommentJPARepository extends JpaRepository { + List findAllByMemberId(Long memberId); + + List findAllByPostId(Long postId); +} diff --git a/src/main/java/com/cow/cow_mvc_practice/comment/service/CommentService.java b/src/main/java/com/cow/cow_mvc_practice/comment/service/CommentService.java new file mode 100644 index 0000000..ab839e9 --- /dev/null +++ b/src/main/java/com/cow/cow_mvc_practice/comment/service/CommentService.java @@ -0,0 +1,18 @@ +package com.cow.cow_mvc_practice.comment.service; + +import java.util.List; + +import com.cow.cow_mvc_practice.comment.controller.dto.request.CommentRequest; +import com.cow.cow_mvc_practice.comment.controller.dto.response.CommentResponse; + +public interface CommentService { + CommentResponse findOne(Long commentId); + + CommentResponse join(Long memberId, Long postId, CommentRequest commentRequest); + + List findAllByPost(Long postId); + + List findAllByMember(Long memberId); + + List findAll(); +} diff --git a/src/main/java/com/cow/cow_mvc_practice/comment/service/CommentServiceImpl.java b/src/main/java/com/cow/cow_mvc_practice/comment/service/CommentServiceImpl.java new file mode 100644 index 0000000..c792fbe --- /dev/null +++ b/src/main/java/com/cow/cow_mvc_practice/comment/service/CommentServiceImpl.java @@ -0,0 +1,75 @@ +package com.cow.cow_mvc_practice.comment.service; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.stream.Collectors; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.cow.cow_mvc_practice.comment.controller.dto.request.CommentRequest; +import com.cow.cow_mvc_practice.comment.controller.dto.response.CommentResponse; +import com.cow.cow_mvc_practice.comment.entity.Comment; +import com.cow.cow_mvc_practice.comment.repository.CommentJPARepository; +import com.cow.cow_mvc_practice.member.entity.Member; +import com.cow.cow_mvc_practice.member.repository.MemberJPARepository; +import com.cow.cow_mvc_practice.post.entity.Post; +import com.cow.cow_mvc_practice.post.repository.PostJPARepository; + +import jakarta.persistence.EntityNotFoundException; +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +@Transactional +public class CommentServiceImpl implements CommentService { + private final CommentJPARepository commentRepository; + private final MemberJPARepository memberRepository; + private final PostJPARepository postRepository; + + @Transactional(readOnly = true) + @Override + public CommentResponse findOne(Long commentId) { + Comment comment = commentRepository.findById(commentId) + .orElseThrow(() -> new EntityNotFoundException("[Error] 댓글을 찾을 수 없습니다.")); + return CommentResponse.from(comment); + } + + @Override + public CommentResponse join(Long memberId, Long postId, CommentRequest commentRequest) { + Member member = this.memberRepository.findById(memberId) + .orElseThrow(() -> new EntityNotFoundException("[Error] 사용자를 찾을 수 없습니다.")); + Post post = this.postRepository.findById(postId) + .orElseThrow(() -> new EntityNotFoundException("[Error] 게시글을 찾을 수 없습니다.")); + Comment comment = Comment.of(commentRequest.getContent(), LocalDateTime.now(), post, member); + commentRepository.save(comment); + return CommentResponse.from(comment); + } + + @Transactional(readOnly = true) + @Override + public List findAllByPost(Long postId) { + List comments = commentRepository.findAllByPostId(postId); + return comments.stream() + .map(CommentResponse::from) + .collect(Collectors.toList()); + } + + @Transactional(readOnly = true) + @Override + public List findAllByMember(Long memberId) { + List comments = commentRepository.findAllByMemberId(memberId); + return comments.stream() + .map(CommentResponse::from) + .collect(Collectors.toList()); + } + + @Transactional(readOnly = true) + @Override + public List findAll() { + List comments = commentRepository.findAll(); + return comments.stream() + .map(CommentResponse::from) + .collect(Collectors.toList()); + } +} diff --git a/src/main/java/com/cow/cow_mvc_practice/member/service/MemberService.java b/src/main/java/com/cow/cow_mvc_practice/member/service/MemberService.java new file mode 100644 index 0000000..5b89b15 --- /dev/null +++ b/src/main/java/com/cow/cow_mvc_practice/member/service/MemberService.java @@ -0,0 +1,21 @@ +package com.cow.cow_mvc_practice.member.service; + +import java.util.List; + +import org.springframework.http.ResponseEntity; + +import com.cow.cow_mvc_practice.member.controller.dto.request.MemberRequest; +import com.cow.cow_mvc_practice.member.controller.dto.request.UpdateMemberRequest; +import com.cow.cow_mvc_practice.member.controller.dto.response.MemberResponse; + +public interface MemberService { + MemberResponse findOne(Long memberId); + + MemberResponse join(MemberRequest memberRequest); + + List findAll(); + + ResponseEntity delete(Long memberId); + + MemberResponse updateById(Long memberId, UpdateMemberRequest updateMemberRequest); +} diff --git a/src/main/java/com/cow/cow_mvc_practice/post/controller/PostController.java b/src/main/java/com/cow/cow_mvc_practice/post/controller/PostController.java new file mode 100644 index 0000000..5e27781 --- /dev/null +++ b/src/main/java/com/cow/cow_mvc_practice/post/controller/PostController.java @@ -0,0 +1,64 @@ +package com.cow.cow_mvc_practice.post.controller; + +import java.util.List; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import com.cow.cow_mvc_practice.post.controller.dto.request.PostRequest; +import com.cow.cow_mvc_practice.post.controller.dto.response.PostResponse; +import com.cow.cow_mvc_practice.post.service.PostService; + +import jakarta.persistence.EntityNotFoundException; +import lombok.RequiredArgsConstructor; + +@RestController +@RequestMapping("/post") +@RequiredArgsConstructor +public class PostController { + private final PostService postService; + + @PostMapping("/new/member/{memberId}") + public PostResponse create(@PathVariable final Long memberId, @RequestBody final PostRequest postRequest) { + return postService.join(memberId, postRequest); + } + + @GetMapping("/{postId}") + public PostResponse findPost(@PathVariable final Long postId) { + return postService.findOne(postId); + } + + @GetMapping() + public PostResponse findPostQuery(@RequestParam("id") final Long postId) { + return postService.findOne(postId); + } + + @GetMapping("/all") + public List findPosts() { + return postService.findAll(); + } + + @GetMapping("/all/member/{memberId}") + public List findPostsByMember(@PathVariable final Long memberId) { + return postService.findAllByMember(memberId); + } + + @DeleteMapping("/{postId}") + public ResponseEntity deletePost(@PathVariable final Long postId) { + return postService.delete(postId); + } + + @ExceptionHandler(EntityNotFoundException.class) + public ResponseEntity handleNoSuchElementFoundException(EntityNotFoundException exception) { + return ResponseEntity.status(HttpStatus.NOT_FOUND).body(exception.getMessage()); + } +} diff --git a/src/main/java/com/cow/cow_mvc_practice/post/controller/dto/request/PostRequest.java b/src/main/java/com/cow/cow_mvc_practice/post/controller/dto/request/PostRequest.java new file mode 100644 index 0000000..6435141 --- /dev/null +++ b/src/main/java/com/cow/cow_mvc_practice/post/controller/dto/request/PostRequest.java @@ -0,0 +1,11 @@ +package com.cow.cow_mvc_practice.post.controller.dto.request; + +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +public class PostRequest { + private String title; + private String content; +} diff --git a/src/main/java/com/cow/cow_mvc_practice/post/controller/dto/request/UpdatePostRequest.java b/src/main/java/com/cow/cow_mvc_practice/post/controller/dto/request/UpdatePostRequest.java new file mode 100644 index 0000000..6c15051 --- /dev/null +++ b/src/main/java/com/cow/cow_mvc_practice/post/controller/dto/request/UpdatePostRequest.java @@ -0,0 +1,14 @@ +package com.cow.cow_mvc_practice.post.controller.dto.request; + +import com.cow.cow_mvc_practice.member.entity.Member; + +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +public class UpdatePostRequest { + private String title; + private String content; + private Member member; +} diff --git a/src/main/java/com/cow/cow_mvc_practice/post/controller/dto/response/PostResponse.java b/src/main/java/com/cow/cow_mvc_practice/post/controller/dto/response/PostResponse.java new file mode 100644 index 0000000..29099fd --- /dev/null +++ b/src/main/java/com/cow/cow_mvc_practice/post/controller/dto/response/PostResponse.java @@ -0,0 +1,49 @@ +package com.cow.cow_mvc_practice.post.controller.dto.response; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.stream.Collectors; + +import com.cow.cow_mvc_practice.comment.entity.Comment; +import com.cow.cow_mvc_practice.post.entity.Post; +import com.fasterxml.jackson.annotation.JsonFormat; + +import lombok.Builder; +import lombok.Getter; + +@Getter +public class PostResponse { + private final Long id; + private final String title; + private final String content; + private final String memberName; + + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss", timezone = "Asia/Seoul") + private final LocalDateTime date; + + private final int commentCount; + private final List comments; + + @Builder + private PostResponse(final Long id, final String title, final String content, + final String memberName, final LocalDateTime date, final List comments) { + this.id = id; + this.title = title; + this.content = content; + this.memberName = memberName; + this.date = date; + this.comments = comments.stream().map(Comment::getContent).collect(Collectors.toList()); + this.commentCount = this.comments.size(); + } + + public static PostResponse from(final Post post) { + return PostResponse.builder() + .id(post.getId()) + .title(post.getTitle()) + .content(post.getContent()) + .memberName(post.getMember().getName()) + .date(post.getDate()) + .comments(post.getComments()) + .build(); + } +} diff --git a/src/main/java/com/cow/cow_mvc_practice/post/repository/PostRepository.java b/src/main/java/com/cow/cow_mvc_practice/post/repository/PostRepository.java new file mode 100644 index 0000000..2c52273 --- /dev/null +++ b/src/main/java/com/cow/cow_mvc_practice/post/repository/PostRepository.java @@ -0,0 +1,15 @@ +package com.cow.cow_mvc_practice.post.repository; + +import java.util.List; +import java.util.Optional; + +import com.cow.cow_mvc_practice.post.entity.Post; + +public interface PostRepository { + + void save(Post post); + + Optional findById(Long postId); + + Optional> findAll(); +} diff --git a/src/main/java/com/cow/cow_mvc_practice/post/repository/PostRepositoryImpl.java b/src/main/java/com/cow/cow_mvc_practice/post/repository/PostRepositoryImpl.java new file mode 100644 index 0000000..61010bb --- /dev/null +++ b/src/main/java/com/cow/cow_mvc_practice/post/repository/PostRepositoryImpl.java @@ -0,0 +1,28 @@ +package com.cow.cow_mvc_practice.post.repository; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +import com.cow.cow_mvc_practice.post.entity.Post; + +public class PostRepositoryImpl implements PostRepository { + + private static final Map store = new HashMap<>(); + + @Override + public void save(Post post) { + store.put(post.getId(), post); + } + + @Override + public Optional findById(Long memberId) { + return Optional.ofNullable(store.get(memberId)); + } + + @Override + public Optional> findAll() { + return Optional.of((List)store.values()); + } +} diff --git a/src/main/java/com/cow/cow_mvc_practice/post/service/PostService.java b/src/main/java/com/cow/cow_mvc_practice/post/service/PostService.java new file mode 100644 index 0000000..eb35d7f --- /dev/null +++ b/src/main/java/com/cow/cow_mvc_practice/post/service/PostService.java @@ -0,0 +1,20 @@ +package com.cow.cow_mvc_practice.post.service; + +import java.util.List; + +import org.springframework.http.ResponseEntity; + +import com.cow.cow_mvc_practice.post.controller.dto.request.PostRequest; +import com.cow.cow_mvc_practice.post.controller.dto.response.PostResponse; + +public interface PostService { + PostResponse findOne(Long postId); + + PostResponse join(Long memberId, PostRequest postRequest); + + List findAll(); + + List findAllByMember(Long memberId); + + ResponseEntity delete(Long postId); +} diff --git a/src/main/java/com/cow/cow_mvc_practice/post/service/PostServiceImpl.java b/src/main/java/com/cow/cow_mvc_practice/post/service/PostServiceImpl.java new file mode 100644 index 0000000..37a4688 --- /dev/null +++ b/src/main/java/com/cow/cow_mvc_practice/post/service/PostServiceImpl.java @@ -0,0 +1,73 @@ +package com.cow.cow_mvc_practice.post.service; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.stream.Collectors; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.cow.cow_mvc_practice.member.entity.Member; +import com.cow.cow_mvc_practice.member.repository.MemberJPARepository; +import com.cow.cow_mvc_practice.post.controller.dto.request.PostRequest; +import com.cow.cow_mvc_practice.post.controller.dto.response.PostResponse; +import com.cow.cow_mvc_practice.post.entity.Post; +import com.cow.cow_mvc_practice.post.repository.PostJPARepository; + +import jakarta.persistence.EntityNotFoundException; +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +@Transactional +public class PostServiceImpl implements PostService { + private final PostJPARepository postRepository; + private final MemberJPARepository memberRepository; + + @Override + public PostResponse join(Long memberId, PostRequest postRequest) { + Member member = memberRepository.findById(memberId) + .orElseThrow(() -> new EntityNotFoundException("[Error] 사용자를 찾을 수 없습니다.")); + Post post = Post.of(postRequest.getTitle(), postRequest.getContent(), member, LocalDateTime.now()); + postRepository.save(post); + return PostResponse.from(post); + } + + @Transactional(readOnly = true) + @Override + public PostResponse findOne(Long postId) { + Post post = postRepository.findById(postId) + .orElseThrow(() -> new EntityNotFoundException("[Error] 게시글을 찾을 수 없습니다.")); + return PostResponse.from(post); + } + + @Transactional(readOnly = true) + @Override + public List findAll() { + List posts = postRepository.findAll(); + return posts.stream() + .map(PostResponse::from) + .collect(Collectors.toList()); + } + + @Transactional(readOnly = true) + @Override + public List findAllByMember(Long memberId) { + List posts = postRepository.findAllByMemberId(memberId); + return posts.stream() + .map(PostResponse::from) + .collect(Collectors.toList()); + } + + @Override + public ResponseEntity delete(Long postId) { + boolean isExistPost = postRepository.existsById(postId); + if (!isExistPost) { + throw new EntityNotFoundException("[Error] 게시글을 찾을 수 없습니다."); + } + postRepository.deleteById(postId); + return new ResponseEntity<>(null, null, HttpStatus.NO_CONTENT); + } +} diff --git a/src/main/java/com/cow/mvc/member/controller/MemberController.java b/src/main/java/com/cow/mvc/member/controller/MemberController.java index 69915ff..5d250a3 100644 --- a/src/main/java/com/cow/mvc/member/controller/MemberController.java +++ b/src/main/java/com/cow/mvc/member/controller/MemberController.java @@ -1,4 +1,4 @@ -package com.cow.mvc.member.controller; +package com.cow.cow_mvc_practice.member.controller; import java.util.List; @@ -15,10 +15,10 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; -import com.cow.mvc.member.controller.dto.request.MemberRequest; -import com.cow.mvc.member.controller.dto.request.UpdateMemberRequest; -import com.cow.mvc.member.controller.dto.response.MemberResponse; -import com.cow.mvc.member.service.MemberService; +import com.cow.cow_mvc_practice.member.controller.dto.request.MemberRequest; +import com.cow.cow_mvc_practice.member.controller.dto.request.UpdateMemberRequest; +import com.cow.cow_mvc_practice.member.controller.dto.response.MemberResponse; +import com.cow.cow_mvc_practice.member.service.MemberService; import jakarta.persistence.EntityNotFoundException; import lombok.RequiredArgsConstructor; diff --git a/src/main/java/com/cow/mvc/member/controller/dto/request/MemberRequest.java b/src/main/java/com/cow/mvc/member/controller/dto/request/MemberRequest.java index d741431..7bdef03 100644 --- a/src/main/java/com/cow/mvc/member/controller/dto/request/MemberRequest.java +++ b/src/main/java/com/cow/mvc/member/controller/dto/request/MemberRequest.java @@ -1,6 +1,6 @@ -package com.cow.mvc.member.controller.dto.request; +package com.cow.cow_mvc_practice.member.controller.dto.request; -import com.cow.mvc.member.entity.Member; +import com.cow.cow_mvc_practice.member.entity.Member; import lombok.Getter; import lombok.NoArgsConstructor; @@ -11,8 +11,6 @@ public class MemberRequest { private String name; public Member toEntity() { - return Member.builder() - .name(this.name) - .build(); + return Member.from(this.name); } } diff --git a/src/main/java/com/cow/mvc/member/controller/dto/response/MemberResponse.java b/src/main/java/com/cow/mvc/member/controller/dto/response/MemberResponse.java index 5740969..e883520 100644 --- a/src/main/java/com/cow/mvc/member/controller/dto/response/MemberResponse.java +++ b/src/main/java/com/cow/mvc/member/controller/dto/response/MemberResponse.java @@ -1,9 +1,9 @@ -package com.cow.mvc.member.controller.dto.response; +package com.cow.cow_mvc_practice.member.controller.dto.response; import java.util.ArrayList; import java.util.List; -import com.cow.mvc.member.entity.Member; +import com.cow.cow_mvc_practice.member.entity.Member; import lombok.Builder; import lombok.Getter; diff --git a/src/main/java/com/cow/mvc/member/entity/Member.java b/src/main/java/com/cow/mvc/member/entity/Member.java index 2d417c2..77bb9b7 100644 --- a/src/main/java/com/cow/mvc/member/entity/Member.java +++ b/src/main/java/com/cow/mvc/member/entity/Member.java @@ -1,10 +1,10 @@ -package com.cow.mvc.member.entity; +package com.cow.cow_mvc_practice.member.entity; import java.util.ArrayList; import java.util.List; -import com.cow.mvc.comment.entity.Comment; -import com.cow.mvc.post.entity.Post; +import com.cow.cow_mvc_practice.comment.entity.Comment; +import com.cow.cow_mvc_practice.post.entity.Post; import jakarta.persistence.CascadeType; import jakarta.persistence.Column; diff --git a/src/main/java/com/cow/mvc/member/service/MemberServiceImpl.java b/src/main/java/com/cow/mvc/member/service/MemberServiceImpl.java index 4e4283b..cea573f 100644 --- a/src/main/java/com/cow/mvc/member/service/MemberServiceImpl.java +++ b/src/main/java/com/cow/mvc/member/service/MemberServiceImpl.java @@ -1,4 +1,4 @@ -package com.cow.mvc.member.service; +package com.cow.cow_mvc_practice.member.service; import java.util.List; import java.util.Optional; @@ -9,11 +9,11 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import com.cow.mvc.member.controller.dto.request.MemberRequest; -import com.cow.mvc.member.controller.dto.request.UpdateMemberRequest; -import com.cow.mvc.member.controller.dto.response.MemberResponse; -import com.cow.mvc.member.entity.Member; -import com.cow.mvc.member.repository.MemberJPARepository; +import com.cow.cow_mvc_practice.member.controller.dto.request.MemberRequest; +import com.cow.cow_mvc_practice.member.controller.dto.request.UpdateMemberRequest; +import com.cow.cow_mvc_practice.member.controller.dto.response.MemberResponse; +import com.cow.cow_mvc_practice.member.entity.Member; +import com.cow.cow_mvc_practice.member.repository.MemberJPARepository; import jakarta.persistence.EntityNotFoundException; import lombok.RequiredArgsConstructor; diff --git a/src/main/java/com/cow/mvc/post/entity/Post.java b/src/main/java/com/cow/mvc/post/entity/Post.java index d61ec3b..3e03109 100644 --- a/src/main/java/com/cow/mvc/post/entity/Post.java +++ b/src/main/java/com/cow/mvc/post/entity/Post.java @@ -1,11 +1,11 @@ -package com.cow.mvc.post.entity; +package com.cow.cow_mvc_practice.post.entity; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; -import com.cow.mvc.comment.entity.Comment; -import com.cow.mvc.member.entity.Member; +import com.cow.cow_mvc_practice.comment.entity.Comment; +import com.cow.cow_mvc_practice.member.entity.Member; import com.fasterxml.jackson.annotation.JsonFormat; import jakarta.persistence.CascadeType; diff --git a/src/main/java/com/cow/mvc/post/repository/PostJPARepository.java b/src/main/java/com/cow/mvc/post/repository/PostJPARepository.java index 472aa1e..bcb6daf 100644 --- a/src/main/java/com/cow/mvc/post/repository/PostJPARepository.java +++ b/src/main/java/com/cow/mvc/post/repository/PostJPARepository.java @@ -1,10 +1,10 @@ -package com.cow.mvc.post.repository; +package com.cow.cow_mvc_practice.post.repository; import java.util.List; import org.springframework.data.jpa.repository.JpaRepository; -import com.cow.mvc.post.entity.Post; +import com.cow.cow_mvc_practice.post.entity.Post; public interface PostJPARepository extends JpaRepository { List findAllByMemberId(Long memberId); diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 7819b3c..7bcd644 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -33,4 +33,4 @@ logging: hibernate: type: descriptor: - sql: trace \ No newline at end of file + sql: trace From d8ea70963e8df2a3ed6e31d867042ff278c26987 Mon Sep 17 00:00:00 2001 From: BuildTools Date: Tue, 21 May 2024 12:39:59 +0900 Subject: [PATCH 14/18] =?UTF-8?q?style=20:=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EC=BB=A8=EB=B2=A4=EC=85=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CowMvcPracticeApplication.java | 2 +- .../dto/request/UpdateCommentRequest.java | 2 +- .../member/controller/MemberController.java | 0 .../controller/dto/request/MemberRequest.java | 0 .../dto/request/UpdateMemberRequest.java | 2 +- .../dto/response/MemberResponse.java | 0 .../member/entity/Member.java | 0 .../repository/MemberJPARepository.java | 4 +- .../member/repository/MemberRepository.java | 4 +- .../repository/MemberRepositoryImpl.java | 4 +- .../member/service/MemberServiceImpl.java | 0 .../post/entity/Post.java | 0 .../post/repository/PostJPARepository.java | 0 .../comment/controller/CommentController.java | 55 -------------- .../dto/request/CommentRequest.java | 11 --- .../dto/response/CommentResponse.java | 41 ---------- .../com/cow/mvc/comment/entity/Comment.java | 60 --------------- .../repository/CommentJPARepository.java | 13 ---- .../mvc/comment/service/CommentService.java | 18 ----- .../comment/service/CommentServiceImpl.java | 75 ------------------- .../cow/mvc/member/service/MemberService.java | 21 ------ .../mvc/post/controller/PostController.java | 64 ---------------- .../controller/dto/request/PostRequest.java | 11 --- .../dto/request/UpdatePostRequest.java | 14 ---- .../controller/dto/response/PostResponse.java | 49 ------------ .../mvc/post/repository/PostRepository.java | 15 ---- .../post/repository/PostRepositoryImpl.java | 28 ------- .../com/cow/mvc/post/service/PostService.java | 20 ----- .../cow/mvc/post/service/PostServiceImpl.java | 73 ------------------ 29 files changed, 9 insertions(+), 577 deletions(-) rename src/main/java/com/cow/{mvc => cow_mvc_practice}/CowMvcPracticeApplication.java (89%) rename src/main/java/com/cow/{mvc => cow_mvc_practice}/comment/controller/dto/request/UpdateCommentRequest.java (69%) rename src/main/java/com/cow/{mvc => cow_mvc_practice}/member/controller/MemberController.java (100%) rename src/main/java/com/cow/{mvc => cow_mvc_practice}/member/controller/dto/request/MemberRequest.java (100%) rename src/main/java/com/cow/{mvc => cow_mvc_practice}/member/controller/dto/request/UpdateMemberRequest.java (69%) rename src/main/java/com/cow/{mvc => cow_mvc_practice}/member/controller/dto/response/MemberResponse.java (100%) rename src/main/java/com/cow/{mvc => cow_mvc_practice}/member/entity/Member.java (100%) rename src/main/java/com/cow/{mvc => cow_mvc_practice}/member/repository/MemberJPARepository.java (57%) rename src/main/java/com/cow/{mvc => cow_mvc_practice}/member/repository/MemberRepository.java (65%) rename src/main/java/com/cow/{mvc => cow_mvc_practice}/member/repository/MemberRepositoryImpl.java (87%) rename src/main/java/com/cow/{mvc => cow_mvc_practice}/member/service/MemberServiceImpl.java (100%) rename src/main/java/com/cow/{mvc => cow_mvc_practice}/post/entity/Post.java (100%) rename src/main/java/com/cow/{mvc => cow_mvc_practice}/post/repository/PostJPARepository.java (100%) delete mode 100644 src/main/java/com/cow/mvc/comment/controller/CommentController.java delete mode 100644 src/main/java/com/cow/mvc/comment/controller/dto/request/CommentRequest.java delete mode 100644 src/main/java/com/cow/mvc/comment/controller/dto/response/CommentResponse.java delete mode 100644 src/main/java/com/cow/mvc/comment/entity/Comment.java delete mode 100644 src/main/java/com/cow/mvc/comment/repository/CommentJPARepository.java delete mode 100644 src/main/java/com/cow/mvc/comment/service/CommentService.java delete mode 100644 src/main/java/com/cow/mvc/comment/service/CommentServiceImpl.java delete mode 100644 src/main/java/com/cow/mvc/member/service/MemberService.java delete mode 100644 src/main/java/com/cow/mvc/post/controller/PostController.java delete mode 100644 src/main/java/com/cow/mvc/post/controller/dto/request/PostRequest.java delete mode 100644 src/main/java/com/cow/mvc/post/controller/dto/request/UpdatePostRequest.java delete mode 100644 src/main/java/com/cow/mvc/post/controller/dto/response/PostResponse.java delete mode 100644 src/main/java/com/cow/mvc/post/repository/PostRepository.java delete mode 100644 src/main/java/com/cow/mvc/post/repository/PostRepositoryImpl.java delete mode 100644 src/main/java/com/cow/mvc/post/service/PostService.java delete mode 100644 src/main/java/com/cow/mvc/post/service/PostServiceImpl.java diff --git a/src/main/java/com/cow/mvc/CowMvcPracticeApplication.java b/src/main/java/com/cow/cow_mvc_practice/CowMvcPracticeApplication.java similarity index 89% rename from src/main/java/com/cow/mvc/CowMvcPracticeApplication.java rename to src/main/java/com/cow/cow_mvc_practice/CowMvcPracticeApplication.java index 6373d4c..677eb51 100644 --- a/src/main/java/com/cow/mvc/CowMvcPracticeApplication.java +++ b/src/main/java/com/cow/cow_mvc_practice/CowMvcPracticeApplication.java @@ -1,4 +1,4 @@ -package com.cow.mvc; +package com.cow.cow_mvc_practice; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; diff --git a/src/main/java/com/cow/mvc/comment/controller/dto/request/UpdateCommentRequest.java b/src/main/java/com/cow/cow_mvc_practice/comment/controller/dto/request/UpdateCommentRequest.java similarity index 69% rename from src/main/java/com/cow/mvc/comment/controller/dto/request/UpdateCommentRequest.java rename to src/main/java/com/cow/cow_mvc_practice/comment/controller/dto/request/UpdateCommentRequest.java index 2269cf8..ab1e043 100644 --- a/src/main/java/com/cow/mvc/comment/controller/dto/request/UpdateCommentRequest.java +++ b/src/main/java/com/cow/cow_mvc_practice/comment/controller/dto/request/UpdateCommentRequest.java @@ -1,4 +1,4 @@ -package com.cow.mvc.comment.controller.dto.request; +package com.cow.cow_mvc_practice.comment.controller.dto.request; import lombok.Getter; import lombok.NoArgsConstructor; diff --git a/src/main/java/com/cow/mvc/member/controller/MemberController.java b/src/main/java/com/cow/cow_mvc_practice/member/controller/MemberController.java similarity index 100% rename from src/main/java/com/cow/mvc/member/controller/MemberController.java rename to src/main/java/com/cow/cow_mvc_practice/member/controller/MemberController.java diff --git a/src/main/java/com/cow/mvc/member/controller/dto/request/MemberRequest.java b/src/main/java/com/cow/cow_mvc_practice/member/controller/dto/request/MemberRequest.java similarity index 100% rename from src/main/java/com/cow/mvc/member/controller/dto/request/MemberRequest.java rename to src/main/java/com/cow/cow_mvc_practice/member/controller/dto/request/MemberRequest.java diff --git a/src/main/java/com/cow/mvc/member/controller/dto/request/UpdateMemberRequest.java b/src/main/java/com/cow/cow_mvc_practice/member/controller/dto/request/UpdateMemberRequest.java similarity index 69% rename from src/main/java/com/cow/mvc/member/controller/dto/request/UpdateMemberRequest.java rename to src/main/java/com/cow/cow_mvc_practice/member/controller/dto/request/UpdateMemberRequest.java index ea30fc9..4edd5c0 100644 --- a/src/main/java/com/cow/mvc/member/controller/dto/request/UpdateMemberRequest.java +++ b/src/main/java/com/cow/cow_mvc_practice/member/controller/dto/request/UpdateMemberRequest.java @@ -1,4 +1,4 @@ -package com.cow.mvc.member.controller.dto.request; +package com.cow.cow_mvc_practice.member.controller.dto.request; import lombok.Getter; import lombok.NoArgsConstructor; diff --git a/src/main/java/com/cow/mvc/member/controller/dto/response/MemberResponse.java b/src/main/java/com/cow/cow_mvc_practice/member/controller/dto/response/MemberResponse.java similarity index 100% rename from src/main/java/com/cow/mvc/member/controller/dto/response/MemberResponse.java rename to src/main/java/com/cow/cow_mvc_practice/member/controller/dto/response/MemberResponse.java diff --git a/src/main/java/com/cow/mvc/member/entity/Member.java b/src/main/java/com/cow/cow_mvc_practice/member/entity/Member.java similarity index 100% rename from src/main/java/com/cow/mvc/member/entity/Member.java rename to src/main/java/com/cow/cow_mvc_practice/member/entity/Member.java diff --git a/src/main/java/com/cow/mvc/member/repository/MemberJPARepository.java b/src/main/java/com/cow/cow_mvc_practice/member/repository/MemberJPARepository.java similarity index 57% rename from src/main/java/com/cow/mvc/member/repository/MemberJPARepository.java rename to src/main/java/com/cow/cow_mvc_practice/member/repository/MemberJPARepository.java index fc72fe7..d98c272 100644 --- a/src/main/java/com/cow/mvc/member/repository/MemberJPARepository.java +++ b/src/main/java/com/cow/cow_mvc_practice/member/repository/MemberJPARepository.java @@ -1,8 +1,8 @@ -package com.cow.mvc.member.repository; +package com.cow.cow_mvc_practice.member.repository; import org.springframework.data.jpa.repository.JpaRepository; -import com.cow.mvc.member.entity.Member; +import com.cow.cow_mvc_practice.member.entity.Member; public interface MemberJPARepository extends JpaRepository { } diff --git a/src/main/java/com/cow/mvc/member/repository/MemberRepository.java b/src/main/java/com/cow/cow_mvc_practice/member/repository/MemberRepository.java similarity index 65% rename from src/main/java/com/cow/mvc/member/repository/MemberRepository.java rename to src/main/java/com/cow/cow_mvc_practice/member/repository/MemberRepository.java index 18d8c31..b9cd48b 100644 --- a/src/main/java/com/cow/mvc/member/repository/MemberRepository.java +++ b/src/main/java/com/cow/cow_mvc_practice/member/repository/MemberRepository.java @@ -1,9 +1,9 @@ -package com.cow.mvc.member.repository; +package com.cow.cow_mvc_practice.member.repository; import java.util.List; import java.util.Optional; -import com.cow.mvc.member.entity.Member; +import com.cow.cow_mvc_practice.member.entity.Member; public interface MemberRepository { diff --git a/src/main/java/com/cow/mvc/member/repository/MemberRepositoryImpl.java b/src/main/java/com/cow/cow_mvc_practice/member/repository/MemberRepositoryImpl.java similarity index 87% rename from src/main/java/com/cow/mvc/member/repository/MemberRepositoryImpl.java rename to src/main/java/com/cow/cow_mvc_practice/member/repository/MemberRepositoryImpl.java index b4ba846..03125fe 100644 --- a/src/main/java/com/cow/mvc/member/repository/MemberRepositoryImpl.java +++ b/src/main/java/com/cow/cow_mvc_practice/member/repository/MemberRepositoryImpl.java @@ -1,4 +1,4 @@ -package com.cow.mvc.member.repository; +package com.cow.cow_mvc_practice.member.repository; import java.util.HashMap; import java.util.List; @@ -7,7 +7,7 @@ import org.springframework.stereotype.Repository; -import com.cow.mvc.member.entity.Member; +import com.cow.cow_mvc_practice.member.entity.Member; @Repository public class MemberRepositoryImpl implements MemberRepository { diff --git a/src/main/java/com/cow/mvc/member/service/MemberServiceImpl.java b/src/main/java/com/cow/cow_mvc_practice/member/service/MemberServiceImpl.java similarity index 100% rename from src/main/java/com/cow/mvc/member/service/MemberServiceImpl.java rename to src/main/java/com/cow/cow_mvc_practice/member/service/MemberServiceImpl.java diff --git a/src/main/java/com/cow/mvc/post/entity/Post.java b/src/main/java/com/cow/cow_mvc_practice/post/entity/Post.java similarity index 100% rename from src/main/java/com/cow/mvc/post/entity/Post.java rename to src/main/java/com/cow/cow_mvc_practice/post/entity/Post.java diff --git a/src/main/java/com/cow/mvc/post/repository/PostJPARepository.java b/src/main/java/com/cow/cow_mvc_practice/post/repository/PostJPARepository.java similarity index 100% rename from src/main/java/com/cow/mvc/post/repository/PostJPARepository.java rename to src/main/java/com/cow/cow_mvc_practice/post/repository/PostJPARepository.java diff --git a/src/main/java/com/cow/mvc/comment/controller/CommentController.java b/src/main/java/com/cow/mvc/comment/controller/CommentController.java deleted file mode 100644 index b77be57..0000000 --- a/src/main/java/com/cow/mvc/comment/controller/CommentController.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.cow.mvc.comment.controller; - -import java.util.List; - -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; - -import com.cow.mvc.comment.controller.dto.request.CommentRequest; -import com.cow.mvc.comment.controller.dto.response.CommentResponse; -import com.cow.mvc.comment.service.CommentService; - -import lombok.RequiredArgsConstructor; - -@RestController -@RequestMapping("/comment") -@RequiredArgsConstructor -public class CommentController { - private final CommentService commentService; - - @PostMapping("/new/member/{memberId}/post/{postId}") - public CommentResponse create(@PathVariable final Long memberId, @PathVariable final Long postId, - @RequestBody final CommentRequest commentRequest) { - return commentService.join(memberId, postId, commentRequest); - } - - @GetMapping("/{commentId}") - public CommentResponse findMember(@PathVariable final Long commentId) { - return commentService.findOne(commentId); - } - - @GetMapping() - public CommentResponse findCommentQuery(@RequestParam("id") final Long commentId) { - return commentService.findOne(commentId); - } - - @GetMapping("all") - public List findComments() { - return commentService.findAll(); - } - - @GetMapping("/all/member/{memberId}") - public List findCommentsByMember(@PathVariable final Long memberId) { - return commentService.findAllByMember(memberId); - } - - @GetMapping("/all/post/{postId}") - public List findCommentsByPost(@PathVariable final Long postId) { - return commentService.findAllByPost(postId); - } -} diff --git a/src/main/java/com/cow/mvc/comment/controller/dto/request/CommentRequest.java b/src/main/java/com/cow/mvc/comment/controller/dto/request/CommentRequest.java deleted file mode 100644 index 5f0b703..0000000 --- a/src/main/java/com/cow/mvc/comment/controller/dto/request/CommentRequest.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.cow.mvc.comment.controller.dto.request; - -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Getter -@NoArgsConstructor -public class CommentRequest { - private String title; - private String content; -} diff --git a/src/main/java/com/cow/mvc/comment/controller/dto/response/CommentResponse.java b/src/main/java/com/cow/mvc/comment/controller/dto/response/CommentResponse.java deleted file mode 100644 index 3deb41b..0000000 --- a/src/main/java/com/cow/mvc/comment/controller/dto/response/CommentResponse.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.cow.mvc.comment.controller.dto.response; - -import java.time.LocalDateTime; - -import com.cow.mvc.comment.entity.Comment; -import com.fasterxml.jackson.annotation.JsonFormat; - -import lombok.Builder; -import lombok.Getter; - -@Getter -public class CommentResponse { - private final Long id; - private final String content; - - @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss", timezone = "Asia/Seoul") - private final LocalDateTime date; - - private final String postTitle; - private final String memberName; - - @Builder - private CommentResponse(final Long id, final String content, final LocalDateTime date, - final String postTitle, final String memberName) { - this.id = id; - this.content = content; - this.date = date; - this.postTitle = postTitle; - this.memberName = memberName; - } - - public static CommentResponse from(final Comment comment) { - return CommentResponse.builder() - .id(comment.getId()) - .content(comment.getContent()) - .date(comment.getDate()) - .postTitle(comment.getPost().getTitle()) - .memberName(comment.getMember().getName()) - .build(); - } -} diff --git a/src/main/java/com/cow/mvc/comment/entity/Comment.java b/src/main/java/com/cow/mvc/comment/entity/Comment.java deleted file mode 100644 index 1031843..0000000 --- a/src/main/java/com/cow/mvc/comment/entity/Comment.java +++ /dev/null @@ -1,60 +0,0 @@ -package com.cow.mvc.comment.entity; - -import java.time.LocalDateTime; - -import com.cow.mvc.member.entity.Member; -import com.cow.mvc.post.entity.Post; -import com.fasterxml.jackson.annotation.JsonFormat; - -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.FetchType; -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; - -@Entity -@Getter -@NoArgsConstructor(access = AccessLevel.PROTECTED) -public class Comment { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "comment_id") - private Long id; - private String content; - - @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss", timezone = "Asia/Seoul") - private LocalDateTime date; - - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "post_id") - private Post post; - - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "member_id") - private Member member; - - @Builder - private Comment(final Long id, final String content, final LocalDateTime date, Post post, Member member) { - this.id = id; - this.content = content; - this.date = date; - this.post = post; - this.member = member; - } - - public static Comment of(String content, LocalDateTime date, Post post, Member member) { - return Comment.builder() - .content(content) - .date(date) - .post(post) - .member(member) - .build(); - } -} diff --git a/src/main/java/com/cow/mvc/comment/repository/CommentJPARepository.java b/src/main/java/com/cow/mvc/comment/repository/CommentJPARepository.java deleted file mode 100644 index baa2b7d..0000000 --- a/src/main/java/com/cow/mvc/comment/repository/CommentJPARepository.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.cow.mvc.comment.repository; - -import java.util.List; - -import org.springframework.data.jpa.repository.JpaRepository; - -import com.cow.mvc.comment.entity.Comment; - -public interface CommentJPARepository extends JpaRepository { - List findAllByMemberId(Long memberId); - - List findAllByPostId(Long postId); -} diff --git a/src/main/java/com/cow/mvc/comment/service/CommentService.java b/src/main/java/com/cow/mvc/comment/service/CommentService.java deleted file mode 100644 index 81bc189..0000000 --- a/src/main/java/com/cow/mvc/comment/service/CommentService.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.cow.mvc.comment.service; - -import java.util.List; - -import com.cow.mvc.comment.controller.dto.request.CommentRequest; -import com.cow.mvc.comment.controller.dto.response.CommentResponse; - -public interface CommentService { - CommentResponse findOne(Long commentId); - - CommentResponse join(Long memberId, Long postId, CommentRequest commentRequest); - - List findAllByPost(Long postId); - - List findAllByMember(Long memberId); - - List findAll(); -} diff --git a/src/main/java/com/cow/mvc/comment/service/CommentServiceImpl.java b/src/main/java/com/cow/mvc/comment/service/CommentServiceImpl.java deleted file mode 100644 index 9e8aa7c..0000000 --- a/src/main/java/com/cow/mvc/comment/service/CommentServiceImpl.java +++ /dev/null @@ -1,75 +0,0 @@ -package com.cow.mvc.comment.service; - -import java.time.LocalDateTime; -import java.util.List; -import java.util.stream.Collectors; - -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import com.cow.mvc.comment.controller.dto.request.CommentRequest; -import com.cow.mvc.comment.controller.dto.response.CommentResponse; -import com.cow.mvc.comment.entity.Comment; -import com.cow.mvc.comment.repository.CommentJPARepository; -import com.cow.mvc.member.entity.Member; -import com.cow.mvc.member.repository.MemberJPARepository; -import com.cow.mvc.post.entity.Post; -import com.cow.mvc.post.repository.PostJPARepository; - -import jakarta.persistence.EntityNotFoundException; -import lombok.RequiredArgsConstructor; - -@Service -@RequiredArgsConstructor -@Transactional -public class CommentServiceImpl implements CommentService { - private final CommentJPARepository commentRepository; - private final MemberJPARepository memberRepository; - private final PostJPARepository postRepository; - - @Transactional(readOnly = true) - @Override - public CommentResponse findOne(Long commentId) { - Comment comment = commentRepository.findById(commentId) - .orElseThrow(() -> new EntityNotFoundException("[Error] 댓글을 찾을 수 없습니다.")); - return CommentResponse.from(comment); - } - - @Override - public CommentResponse join(Long memberId, Long postId, CommentRequest commentRequest) { - Member member = this.memberRepository.findById(memberId) - .orElseThrow(() -> new EntityNotFoundException("[Error] 사용자를 찾을 수 없습니다.")); - Post post = this.postRepository.findById(postId) - .orElseThrow(() -> new EntityNotFoundException("[Error] 게시글을 찾을 수 없습니다.")); - Comment comment = Comment.of(commentRequest.getContent(), LocalDateTime.now(), post, member); - commentRepository.save(comment); - return CommentResponse.from(comment); - } - - @Transactional(readOnly = true) - @Override - public List findAllByPost(Long postId) { - List comments = commentRepository.findAllByPostId(postId); - return comments.stream() - .map(CommentResponse::from) - .collect(Collectors.toList()); - } - - @Transactional(readOnly = true) - @Override - public List findAllByMember(Long memberId) { - List comments = commentRepository.findAllByMemberId(memberId); - return comments.stream() - .map(CommentResponse::from) - .collect(Collectors.toList()); - } - - @Transactional(readOnly = true) - @Override - public List findAll() { - List comments = commentRepository.findAll(); - return comments.stream() - .map(CommentResponse::from) - .collect(Collectors.toList()); - } -} diff --git a/src/main/java/com/cow/mvc/member/service/MemberService.java b/src/main/java/com/cow/mvc/member/service/MemberService.java deleted file mode 100644 index 1a793b8..0000000 --- a/src/main/java/com/cow/mvc/member/service/MemberService.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.cow.mvc.member.service; - -import java.util.List; - -import org.springframework.http.ResponseEntity; - -import com.cow.mvc.member.controller.dto.request.MemberRequest; -import com.cow.mvc.member.controller.dto.request.UpdateMemberRequest; -import com.cow.mvc.member.controller.dto.response.MemberResponse; - -public interface MemberService { - MemberResponse findOne(Long memberId); - - MemberResponse join(MemberRequest memberRequest); - - List findAll(); - - ResponseEntity delete(Long memberId); - - MemberResponse updateById(Long memberId, UpdateMemberRequest updateMemberRequest); -} diff --git a/src/main/java/com/cow/mvc/post/controller/PostController.java b/src/main/java/com/cow/mvc/post/controller/PostController.java deleted file mode 100644 index f7bc4a3..0000000 --- a/src/main/java/com/cow/mvc/post/controller/PostController.java +++ /dev/null @@ -1,64 +0,0 @@ -package com.cow.mvc.post.controller; - -import java.util.List; - -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.ExceptionHandler; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; - -import com.cow.mvc.post.controller.dto.request.PostRequest; -import com.cow.mvc.post.controller.dto.response.PostResponse; -import com.cow.mvc.post.service.PostService; - -import jakarta.persistence.EntityNotFoundException; -import lombok.RequiredArgsConstructor; - -@RestController -@RequestMapping("/post") -@RequiredArgsConstructor -public class PostController { - private final PostService postService; - - @PostMapping("/new/member/{memberId}") - public PostResponse create(@PathVariable final Long memberId, @RequestBody final PostRequest postRequest) { - return postService.join(memberId, postRequest); - } - - @GetMapping("/{postId}") - public PostResponse findPost(@PathVariable final Long postId) { - return postService.findOne(postId); - } - - @GetMapping() - public PostResponse findPostQuery(@RequestParam("id") final Long postId) { - return postService.findOne(postId); - } - - @GetMapping("/all") - public List findPosts() { - return postService.findAll(); - } - - @GetMapping("/all/member/{memberId}") - public List findPostsByMember(@PathVariable final Long memberId) { - return postService.findAllByMember(memberId); - } - - @DeleteMapping("/{postId}") - public ResponseEntity deletePost(@PathVariable final Long postId) { - return postService.delete(postId); - } - - @ExceptionHandler(EntityNotFoundException.class) - public ResponseEntity handleNoSuchElementFoundException(EntityNotFoundException exception) { - return ResponseEntity.status(HttpStatus.NOT_FOUND).body(exception.getMessage()); - } -} diff --git a/src/main/java/com/cow/mvc/post/controller/dto/request/PostRequest.java b/src/main/java/com/cow/mvc/post/controller/dto/request/PostRequest.java deleted file mode 100644 index 9053092..0000000 --- a/src/main/java/com/cow/mvc/post/controller/dto/request/PostRequest.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.cow.mvc.post.controller.dto.request; - -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Getter -@NoArgsConstructor -public class PostRequest { - private String title; - private String content; -} diff --git a/src/main/java/com/cow/mvc/post/controller/dto/request/UpdatePostRequest.java b/src/main/java/com/cow/mvc/post/controller/dto/request/UpdatePostRequest.java deleted file mode 100644 index a2e87b7..0000000 --- a/src/main/java/com/cow/mvc/post/controller/dto/request/UpdatePostRequest.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.cow.mvc.post.controller.dto.request; - -import com.cow.mvc.member.entity.Member; - -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Getter -@NoArgsConstructor -public class UpdatePostRequest { - private String title; - private String content; - private Member member; -} diff --git a/src/main/java/com/cow/mvc/post/controller/dto/response/PostResponse.java b/src/main/java/com/cow/mvc/post/controller/dto/response/PostResponse.java deleted file mode 100644 index 33fc3f1..0000000 --- a/src/main/java/com/cow/mvc/post/controller/dto/response/PostResponse.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.cow.mvc.post.controller.dto.response; - -import java.time.LocalDateTime; -import java.util.List; -import java.util.stream.Collectors; - -import com.cow.mvc.comment.entity.Comment; -import com.cow.mvc.post.entity.Post; -import com.fasterxml.jackson.annotation.JsonFormat; - -import lombok.Builder; -import lombok.Getter; - -@Getter -public class PostResponse { - private final Long id; - private final String title; - private final String content; - private final String memberName; - - @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss", timezone = "Asia/Seoul") - private final LocalDateTime date; - - private final int commentCount; - private final List comments; - - @Builder - private PostResponse(final Long id, final String title, final String content, - final String memberName, final LocalDateTime date, final List comments) { - this.id = id; - this.title = title; - this.content = content; - this.memberName = memberName; - this.date = date; - this.comments = comments.stream().map(Comment::getContent).collect(Collectors.toList()); - this.commentCount = this.comments.size(); - } - - public static PostResponse from(final Post post) { - return PostResponse.builder() - .id(post.getId()) - .title(post.getTitle()) - .content(post.getContent()) - .memberName(post.getMember().getName()) - .date(post.getDate()) - .comments(post.getComments()) - .build(); - } -} diff --git a/src/main/java/com/cow/mvc/post/repository/PostRepository.java b/src/main/java/com/cow/mvc/post/repository/PostRepository.java deleted file mode 100644 index 7cfe581..0000000 --- a/src/main/java/com/cow/mvc/post/repository/PostRepository.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.cow.mvc.post.repository; - -import java.util.List; -import java.util.Optional; - -import com.cow.mvc.post.entity.Post; - -public interface PostRepository { - - void save(Post post); - - Optional findById(Long postId); - - Optional> findAll(); -} diff --git a/src/main/java/com/cow/mvc/post/repository/PostRepositoryImpl.java b/src/main/java/com/cow/mvc/post/repository/PostRepositoryImpl.java deleted file mode 100644 index e132e57..0000000 --- a/src/main/java/com/cow/mvc/post/repository/PostRepositoryImpl.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.cow.mvc.post.repository; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; - -import com.cow.mvc.post.entity.Post; - -public class PostRepositoryImpl implements PostRepository { - - private static final Map store = new HashMap<>(); - - @Override - public void save(Post post) { - store.put(post.getId(), post); - } - - @Override - public Optional findById(Long memberId) { - return Optional.ofNullable(store.get(memberId)); - } - - @Override - public Optional> findAll() { - return Optional.of((List)store.values()); - } -} diff --git a/src/main/java/com/cow/mvc/post/service/PostService.java b/src/main/java/com/cow/mvc/post/service/PostService.java deleted file mode 100644 index 5c21832..0000000 --- a/src/main/java/com/cow/mvc/post/service/PostService.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.cow.mvc.post.service; - -import java.util.List; - -import org.springframework.http.ResponseEntity; - -import com.cow.mvc.post.controller.dto.request.PostRequest; -import com.cow.mvc.post.controller.dto.response.PostResponse; - -public interface PostService { - PostResponse findOne(Long postId); - - PostResponse join(Long memberId, PostRequest postRequest); - - List findAll(); - - List findAllByMember(Long memberId); - - ResponseEntity delete(Long postId); -} diff --git a/src/main/java/com/cow/mvc/post/service/PostServiceImpl.java b/src/main/java/com/cow/mvc/post/service/PostServiceImpl.java deleted file mode 100644 index 0cbf650..0000000 --- a/src/main/java/com/cow/mvc/post/service/PostServiceImpl.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.cow.mvc.post.service; - -import java.time.LocalDateTime; -import java.util.List; -import java.util.stream.Collectors; - -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import com.cow.mvc.member.entity.Member; -import com.cow.mvc.member.repository.MemberJPARepository; -import com.cow.mvc.post.controller.dto.request.PostRequest; -import com.cow.mvc.post.controller.dto.response.PostResponse; -import com.cow.mvc.post.entity.Post; -import com.cow.mvc.post.repository.PostJPARepository; - -import jakarta.persistence.EntityNotFoundException; -import lombok.RequiredArgsConstructor; - -@Service -@RequiredArgsConstructor -@Transactional -public class PostServiceImpl implements PostService { - private final PostJPARepository postRepository; - private final MemberJPARepository memberRepository; - - @Override - public PostResponse join(Long memberId, PostRequest postRequest) { - Member member = memberRepository.findById(memberId) - .orElseThrow(() -> new EntityNotFoundException("[Error] 사용자를 찾을 수 없습니다.")); - Post post = Post.of(postRequest.getTitle(), postRequest.getContent(), member, LocalDateTime.now()); - postRepository.save(post); - return PostResponse.from(post); - } - - @Transactional(readOnly = true) - @Override - public PostResponse findOne(Long postId) { - Post post = postRepository.findById(postId) - .orElseThrow(() -> new EntityNotFoundException("[Error] 게시글을 찾을 수 없습니다.")); - return PostResponse.from(post); - } - - @Transactional(readOnly = true) - @Override - public List findAll() { - List posts = postRepository.findAll(); - return posts.stream() - .map(PostResponse::from) - .collect(Collectors.toList()); - } - - @Transactional(readOnly = true) - @Override - public List findAllByMember(Long memberId) { - List posts = postRepository.findAllByMemberId(memberId); - return posts.stream() - .map(PostResponse::from) - .collect(Collectors.toList()); - } - - @Override - public ResponseEntity delete(Long postId) { - boolean isExistPost = postRepository.existsById(postId); - if (!isExistPost) { - throw new EntityNotFoundException("[Error] 게시글을 찾을 수 없습니다."); - } - postRepository.deleteById(postId); - return new ResponseEntity<>(null, null, HttpStatus.NO_CONTENT); - } -} From b662d27788c3496926457af7c80199df01349ffa Mon Sep 17 00:00:00 2001 From: BuildTools Date: Thu, 20 Jun 2024 18:01:05 +0900 Subject: [PATCH 15/18] =?UTF-8?q?feat=20:=20=ED=94=84=EB=A1=9C=ED=95=84=20?= =?UTF-8?q?=EC=9D=B4=EB=AF=B8=EC=A7=80=20s3=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 3 ++ build.gradle | 1 + gradlew | 0 .../Image/service/ImageUploadService.java | 9 ++++ .../Image/service/ImageUploadServiceImpl.java | 46 +++++++++++++++++++ .../cow/cow_mvc_practice/config/S3Config.java | 31 +++++++++++++ .../member/controller/MemberController.java | 11 +++++ .../dto/response/MemberResponse.java | 5 +- .../member/entity/Member.java | 6 +++ .../member/service/MemberService.java | 2 + .../member/service/MemberServiceImpl.java | 9 ++++ src/main/resources/application.yml | 2 + 12 files changed, 124 insertions(+), 1 deletion(-) mode change 100755 => 100644 gradlew create mode 100644 src/main/java/com/cow/cow_mvc_practice/Image/service/ImageUploadService.java create mode 100644 src/main/java/com/cow/cow_mvc_practice/Image/service/ImageUploadServiceImpl.java create mode 100644 src/main/java/com/cow/cow_mvc_practice/config/S3Config.java diff --git a/.gitignore b/.gitignore index c2065bc..039509d 100644 --- a/.gitignore +++ b/.gitignore @@ -35,3 +35,6 @@ out/ ### VS Code ### .vscode/ + +### Security ### +application-aws.yml diff --git a/build.gradle b/build.gradle index b3bb126..bfba133 100644 --- a/build.gradle +++ b/build.gradle @@ -22,6 +22,7 @@ repositories { } dependencies { + implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE' implementation 'mysql:mysql-connector-java:8.0.32' implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-web' diff --git a/gradlew b/gradlew old mode 100755 new mode 100644 diff --git a/src/main/java/com/cow/cow_mvc_practice/Image/service/ImageUploadService.java b/src/main/java/com/cow/cow_mvc_practice/Image/service/ImageUploadService.java new file mode 100644 index 0000000..be27e36 --- /dev/null +++ b/src/main/java/com/cow/cow_mvc_practice/Image/service/ImageUploadService.java @@ -0,0 +1,9 @@ +package com.cow.cow_mvc_practice.Image.service; + +import java.io.IOException; + +import org.springframework.web.multipart.MultipartFile; + +public interface ImageUploadService { + String upload(MultipartFile image) throws IOException; +} diff --git a/src/main/java/com/cow/cow_mvc_practice/Image/service/ImageUploadServiceImpl.java b/src/main/java/com/cow/cow_mvc_practice/Image/service/ImageUploadServiceImpl.java new file mode 100644 index 0000000..f0bb267 --- /dev/null +++ b/src/main/java/com/cow/cow_mvc_practice/Image/service/ImageUploadServiceImpl.java @@ -0,0 +1,46 @@ +package com.cow.cow_mvc_practice.Image.service; + +import java.io.IOException; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; + +import com.amazonaws.services.s3.AmazonS3Client; +import com.amazonaws.services.s3.model.ObjectMetadata; + +@Service +@Transactional +public class ImageUploadServiceImpl implements ImageUploadService { + private final AmazonS3Client s3Client; + + @Autowired + public ImageUploadServiceImpl(AmazonS3Client s3Client) { + this.s3Client = s3Client; + } + + @Value("${s3.bucket}") + private String bucket; + + public String upload(MultipartFile image) throws IOException { + String originalFileName = image.getOriginalFilename(); + String fileName = changeFileName(originalFileName); + + ObjectMetadata metadata = new ObjectMetadata(); + metadata.setContentType(image.getContentType()); + metadata.setContentLength(image.getSize()); + + s3Client.putObject(bucket, fileName, image.getInputStream(), metadata); + + return s3Client.getUrl(bucket, fileName).toString(); + } + + private String changeFileName(String originalFileName) { + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss"); + return originalFileName + "_" + LocalDateTime.now().format(formatter); + } +} diff --git a/src/main/java/com/cow/cow_mvc_practice/config/S3Config.java b/src/main/java/com/cow/cow_mvc_practice/config/S3Config.java new file mode 100644 index 0000000..d544ec4 --- /dev/null +++ b/src/main/java/com/cow/cow_mvc_practice/config/S3Config.java @@ -0,0 +1,31 @@ +package com.cow.cow_mvc_practice.config; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import com.amazonaws.auth.AWSStaticCredentialsProvider; +import com.amazonaws.auth.BasicAWSCredentials; +import com.amazonaws.services.s3.AmazonS3Client; + +@Configuration +public class S3Config { + @Value("${s3.credentials.access-key}") + private String accessKey; + + @Value("${s3.credentials.secret-key}") + private String secretKey; + + @Value("${s3.credentials.region}") + private String region; + + @Bean + public AmazonS3Client s3Client() { + BasicAWSCredentials awsCredentials = new BasicAWSCredentials(accessKey, secretKey); + + return (AmazonS3Client)AmazonS3Client.builder() + .withRegion(region) + .withCredentials(new AWSStaticCredentialsProvider(awsCredentials)) + .build(); + } +} diff --git a/src/main/java/com/cow/cow_mvc_practice/member/controller/MemberController.java b/src/main/java/com/cow/cow_mvc_practice/member/controller/MemberController.java index 5d250a3..44ef93a 100644 --- a/src/main/java/com/cow/cow_mvc_practice/member/controller/MemberController.java +++ b/src/main/java/com/cow/cow_mvc_practice/member/controller/MemberController.java @@ -1,5 +1,6 @@ package com.cow.cow_mvc_practice.member.controller; +import java.io.IOException; import java.util.List; import org.springframework.http.HttpStatus; @@ -14,7 +15,9 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; +import com.cow.cow_mvc_practice.Image.service.ImageUploadService; import com.cow.cow_mvc_practice.member.controller.dto.request.MemberRequest; import com.cow.cow_mvc_practice.member.controller.dto.request.UpdateMemberRequest; import com.cow.cow_mvc_practice.member.controller.dto.response.MemberResponse; @@ -28,6 +31,7 @@ @RequiredArgsConstructor public class MemberController { private final MemberService memberService; + private final ImageUploadService imageUploadService; @PostMapping("/new") public MemberResponse create(@RequestBody final MemberRequest memberRequest) { @@ -55,6 +59,13 @@ public MemberResponse update(@PathVariable final Long memberId, return memberService.updateById(memberId, updateMemberRequest); } + @PatchMapping(value = "/{memberId}/image") + public MemberResponse updateProfileImage(@PathVariable final Long memberId, + @RequestParam("image") MultipartFile multipartFile) throws IOException { + String profileImage = imageUploadService.upload(multipartFile); + return memberService.updateImageById(memberId, profileImage); + } + @DeleteMapping("/{memberId}") public ResponseEntity delete(@PathVariable final Long memberId) { return memberService.delete(memberId); diff --git a/src/main/java/com/cow/cow_mvc_practice/member/controller/dto/response/MemberResponse.java b/src/main/java/com/cow/cow_mvc_practice/member/controller/dto/response/MemberResponse.java index e883520..a072865 100644 --- a/src/main/java/com/cow/cow_mvc_practice/member/controller/dto/response/MemberResponse.java +++ b/src/main/java/com/cow/cow_mvc_practice/member/controller/dto/response/MemberResponse.java @@ -12,12 +12,14 @@ public class MemberResponse { private final Long id; private final String name; + private final String profileImage; private final List posts; @Builder - private MemberResponse(final Long id, final String name, final List posts) { + private MemberResponse(final Long id, final String name, final String profileImage, final List posts) { this.id = id; this.name = name; + this.profileImage = profileImage; this.posts = posts; } @@ -27,6 +29,7 @@ public static MemberResponse from(final Member member) { return MemberResponse.builder() .id(member.getId()) .name(member.getName()) + .profileImage(member.getProfileImage()) .posts(posts) .build(); } diff --git a/src/main/java/com/cow/cow_mvc_practice/member/entity/Member.java b/src/main/java/com/cow/cow_mvc_practice/member/entity/Member.java index 77bb9b7..66e054c 100644 --- a/src/main/java/com/cow/cow_mvc_practice/member/entity/Member.java +++ b/src/main/java/com/cow/cow_mvc_practice/member/entity/Member.java @@ -27,6 +27,7 @@ public class Member { @Column(name = "member_id") private Long id; private String name; + private String profileImage; // URL @OneToMany(mappedBy = "member", cascade = CascadeType.ALL) private final List posts = new ArrayList<>(); @@ -38,6 +39,7 @@ public class Member { private Member(final Long id, final String name) { this.id = id; this.name = name; + this.profileImage = "https://mycowpracticebucket.s3.ap-northeast-2.amazonaws.com/anonymous.png"; } public static Member from(String name) { @@ -49,4 +51,8 @@ public static Member from(String name) { public void updateMemberName(String name) { this.name = name; } + + public void updateProfileImage(String profileImage) { + this.profileImage = profileImage; + } } diff --git a/src/main/java/com/cow/cow_mvc_practice/member/service/MemberService.java b/src/main/java/com/cow/cow_mvc_practice/member/service/MemberService.java index 5b89b15..18af7cc 100644 --- a/src/main/java/com/cow/cow_mvc_practice/member/service/MemberService.java +++ b/src/main/java/com/cow/cow_mvc_practice/member/service/MemberService.java @@ -18,4 +18,6 @@ public interface MemberService { ResponseEntity delete(Long memberId); MemberResponse updateById(Long memberId, UpdateMemberRequest updateMemberRequest); + + MemberResponse updateImageById(Long memberId, String profileImage); } diff --git a/src/main/java/com/cow/cow_mvc_practice/member/service/MemberServiceImpl.java b/src/main/java/com/cow/cow_mvc_practice/member/service/MemberServiceImpl.java index cea573f..3c82125 100644 --- a/src/main/java/com/cow/cow_mvc_practice/member/service/MemberServiceImpl.java +++ b/src/main/java/com/cow/cow_mvc_practice/member/service/MemberServiceImpl.java @@ -66,4 +66,13 @@ public MemberResponse updateById(Long memberId, UpdateMemberRequest updateMember member.updateMemberName(name); return MemberResponse.from(member); } + + @Override + public MemberResponse updateImageById(Long memberId, String profileImage) { + Member member = memberRepository.findById(memberId) + .orElseThrow(() -> new EntityNotFoundException("[Error] 사용자를 찾을 수 없습니다.")); + profileImage = Optional.ofNullable(profileImage).orElseThrow(IllegalArgumentException::new); + member.updateProfileImage(profileImage); + return MemberResponse.from(member); + } } diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 7bcd644..a6519b0 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -1,6 +1,8 @@ spring: application: name: cow_mvc_practice + profiles: + include: aws jpa: open-in-view: true hibernate: From 3682a4db068c497b3498856a21a0f622f26fe221 Mon Sep 17 00:00:00 2001 From: BuildTools Date: Fri, 21 Jun 2024 14:59:27 +0900 Subject: [PATCH 16/18] =?UTF-8?q?feat=20:=20swagger=20=EB=AC=B8=EC=84=9C?= =?UTF-8?q?=ED=99=94=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 3 + .../comment/controller/CommentController.java | 61 +++++++++++++++++++ .../dto/request/CommentRequest.java | 6 +- .../dto/request/UpdateCommentRequest.java | 10 --- .../dto/response/CommentResponse.java | 9 +++ .../config/SwaggerConfig.java | 41 +++++++++++++ .../member/controller/MemberController.java | 55 +++++++++++++++++ .../controller/dto/request/MemberRequest.java | 8 +++ .../dto/request/UpdateMemberRequest.java | 3 + .../dto/response/MemberResponse.java | 9 +++ .../post/controller/PostController.java | 52 ++++++++++++++++ .../controller/dto/request/PostRequest.java | 8 +++ .../dto/request/UpdatePostRequest.java | 14 ----- .../controller/dto/response/PostResponse.java | 14 +++++ src/main/resources/application.yml | 19 ++++++ 15 files changed, 287 insertions(+), 25 deletions(-) delete mode 100644 src/main/java/com/cow/cow_mvc_practice/comment/controller/dto/request/UpdateCommentRequest.java create mode 100644 src/main/java/com/cow/cow_mvc_practice/config/SwaggerConfig.java delete mode 100644 src/main/java/com/cow/cow_mvc_practice/post/controller/dto/request/UpdatePostRequest.java diff --git a/build.gradle b/build.gradle index bfba133..233c1a5 100644 --- a/build.gradle +++ b/build.gradle @@ -22,6 +22,9 @@ repositories { } dependencies { + implementation 'io.springfox:springfox-swagger2:2.9.2' + implementation 'io.springfox:springfox-swagger-ui:2.9.2' + implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.0.2' implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE' implementation 'mysql:mysql-connector-java:8.0.32' implementation 'org.springframework.boot:spring-boot-starter-data-jpa' diff --git a/src/main/java/com/cow/cow_mvc_practice/comment/controller/CommentController.java b/src/main/java/com/cow/cow_mvc_practice/comment/controller/CommentController.java index b255c95..aeef992 100644 --- a/src/main/java/com/cow/cow_mvc_practice/comment/controller/CommentController.java +++ b/src/main/java/com/cow/cow_mvc_practice/comment/controller/CommentController.java @@ -2,20 +2,33 @@ import java.util.List; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestController; import com.cow.cow_mvc_practice.comment.controller.dto.request.CommentRequest; import com.cow.cow_mvc_practice.comment.controller.dto.response.CommentResponse; import com.cow.cow_mvc_practice.comment.service.CommentService; +import com.cow.cow_mvc_practice.member.controller.dto.response.MemberResponse; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.persistence.EntityNotFoundException; import lombok.RequiredArgsConstructor; +@Tag(name = "Comment", description = "댓글 관련 API") @RestController @RequestMapping("/comment") @RequiredArgsConstructor @@ -23,33 +36,81 @@ public class CommentController { private final CommentService commentService; @PostMapping("/new/member/{memberId}/post/{postId}") + @Operation(summary = "등록", description = "신규 댓글 등록") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "등록 성공", + content = {@Content(schema = @Schema(implementation = MemberResponse.class))}), + @ApiResponse(responseCode = "400", description = "잘못된 요청", + content = {@Content(schema = @Schema(hidden = true))}), + @ApiResponse(responseCode = "404", description = "존재하지 않는 게시글 또는 회원", + content = {@Content(schema = @Schema(hidden = true))}) + }) public CommentResponse create(@PathVariable final Long memberId, @PathVariable final Long postId, @RequestBody final CommentRequest commentRequest) { return commentService.join(memberId, postId, commentRequest); } @GetMapping("/{commentId}") + @Operation(summary = "조회", description = "기존 댓글 조회") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "조회 성공", + content = {@Content(schema = @Schema(implementation = MemberResponse.class))}), + @ApiResponse(responseCode = "404", description = "존재하지 않는 댓글", + content = {@Content(schema = @Schema(hidden = true))}) + }) public CommentResponse findMember(@PathVariable final Long commentId) { return commentService.findOne(commentId); } @GetMapping() + @Operation(summary = "조회", description = "기존 댓글 조회") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "조회 성공", + content = {@Content(schema = @Schema(implementation = MemberResponse.class))}), + @ApiResponse(responseCode = "404", description = "존재하지 않는 댓글", + content = {@Content(schema = @Schema(hidden = true))}) + }) public CommentResponse findCommentQuery(@RequestParam("id") final Long commentId) { return commentService.findOne(commentId); } @GetMapping("all") + @Operation(summary = "전체 조회", description = "모든 댓글 조회") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "조회 성공", + content = {@Content(schema = @Schema(implementation = MemberResponse.class))}) + }) public List findComments() { return commentService.findAll(); } @GetMapping("/all/member/{memberId}") + @Operation(summary = "회원의 전체 댓글 조회", description = "특정 회원 ID로 작성된 모든 댓글 조회") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "조회 성공", + content = {@Content(schema = @Schema(implementation = MemberResponse.class))}), + @ApiResponse(responseCode = "404", description = "존재하지 않는 회원", + content = {@Content(schema = @Schema(hidden = true))}) + }) public List findCommentsByMember(@PathVariable final Long memberId) { return commentService.findAllByMember(memberId); } @GetMapping("/all/post/{postId}") + @Operation(summary = "게시글의 전체 댓글 조회", description = "특정 게시글의 모든 댓글 조회") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "등록 성공", + content = {@Content(schema = @Schema(implementation = MemberResponse.class))}), + @ApiResponse(responseCode = "404", description = "존재하지 않는 게시글", + content = {@Content(schema = @Schema(hidden = true))}) + }) public List findCommentsByPost(@PathVariable final Long postId) { return commentService.findAllByPost(postId); } + + @ResponseStatus(HttpStatus.NOT_FOUND) + @ExceptionHandler(EntityNotFoundException.class) + public ResponseEntity handleNoSuchElementFoundException(EntityNotFoundException exception) { + return ResponseEntity.status(HttpStatus.NOT_FOUND).body(exception.getMessage()); + } } diff --git a/src/main/java/com/cow/cow_mvc_practice/comment/controller/dto/request/CommentRequest.java b/src/main/java/com/cow/cow_mvc_practice/comment/controller/dto/request/CommentRequest.java index 98849a2..d810bbb 100644 --- a/src/main/java/com/cow/cow_mvc_practice/comment/controller/dto/request/CommentRequest.java +++ b/src/main/java/com/cow/cow_mvc_practice/comment/controller/dto/request/CommentRequest.java @@ -1,11 +1,15 @@ package com.cow.cow_mvc_practice.comment.controller.dto.request; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; import lombok.Getter; import lombok.NoArgsConstructor; @Getter @NoArgsConstructor +@Schema(title = "Comment Request : 댓글 등록 요청 DTO") public class CommentRequest { - private String title; + @NotBlank(message = "댓글 내용을 입력해주세요.") + @Schema(description = "댓글 내용") private String content; } diff --git a/src/main/java/com/cow/cow_mvc_practice/comment/controller/dto/request/UpdateCommentRequest.java b/src/main/java/com/cow/cow_mvc_practice/comment/controller/dto/request/UpdateCommentRequest.java deleted file mode 100644 index ab1e043..0000000 --- a/src/main/java/com/cow/cow_mvc_practice/comment/controller/dto/request/UpdateCommentRequest.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.cow.cow_mvc_practice.comment.controller.dto.request; - -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Getter -@NoArgsConstructor -public class UpdateCommentRequest { - private String title; -} diff --git a/src/main/java/com/cow/cow_mvc_practice/comment/controller/dto/response/CommentResponse.java b/src/main/java/com/cow/cow_mvc_practice/comment/controller/dto/response/CommentResponse.java index 02e2274..21a6e49 100644 --- a/src/main/java/com/cow/cow_mvc_practice/comment/controller/dto/response/CommentResponse.java +++ b/src/main/java/com/cow/cow_mvc_practice/comment/controller/dto/response/CommentResponse.java @@ -5,18 +5,27 @@ import com.cow.cow_mvc_practice.comment.entity.Comment; import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Builder; import lombok.Getter; @Getter +@Schema(title = "Comment Response : 댓글 결과 DTO") public class CommentResponse { + @Schema(description = "댓글 ID") private final Long id; + + @Schema(description = "내용") private final String content; + @Schema(description = "작성 날짜") @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss", timezone = "Asia/Seoul") private final LocalDateTime date; + @Schema(description = "게시글 제목") private final String postTitle; + + @Schema(description = "댓글 작성자 ID") private final String memberName; @Builder diff --git a/src/main/java/com/cow/cow_mvc_practice/config/SwaggerConfig.java b/src/main/java/com/cow/cow_mvc_practice/config/SwaggerConfig.java new file mode 100644 index 0000000..4a259a2 --- /dev/null +++ b/src/main/java/com/cow/cow_mvc_practice/config/SwaggerConfig.java @@ -0,0 +1,41 @@ +package com.cow.cow_mvc_practice.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import io.swagger.v3.oas.annotations.OpenAPIDefinition; +import io.swagger.v3.oas.annotations.info.Info; +import io.swagger.v3.oas.models.Components; +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.security.SecurityRequirement; +import io.swagger.v3.oas.models.security.SecurityScheme; + +@OpenAPIDefinition( + info = @Info( + title = "Cow Practice", + description = "COW_MVC 연습 프로젝트", + version = "1.0.0" + ) +) +@Configuration +public class SwaggerConfig { + + private static final String BEARER_TOKEN_PREFIX = "Bearer"; + + @Bean + public OpenAPI openAPI() { + String securityJwtName = "JWT"; + SecurityRequirement securityRequirement = new SecurityRequirement().addList(securityJwtName); + Components components = new Components() + .addSecuritySchemes(securityJwtName, new SecurityScheme() + .name(securityJwtName) + .type(SecurityScheme.Type.HTTP) + .scheme(BEARER_TOKEN_PREFIX) + .bearerFormat(securityJwtName)); + + return new OpenAPI() + .addSecurityItem(securityRequirement) + .components(components); + } + +} diff --git a/src/main/java/com/cow/cow_mvc_practice/member/controller/MemberController.java b/src/main/java/com/cow/cow_mvc_practice/member/controller/MemberController.java index 44ef93a..dfa3f9d 100644 --- a/src/main/java/com/cow/cow_mvc_practice/member/controller/MemberController.java +++ b/src/main/java/com/cow/cow_mvc_practice/member/controller/MemberController.java @@ -14,6 +14,7 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; @@ -23,9 +24,16 @@ import com.cow.cow_mvc_practice.member.controller.dto.response.MemberResponse; import com.cow.cow_mvc_practice.member.service.MemberService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.persistence.EntityNotFoundException; import lombok.RequiredArgsConstructor; +@Tag(name = "Member", description = "회원 관련 API") @RestController @RequestMapping("/member") @RequiredArgsConstructor @@ -34,32 +42,71 @@ public class MemberController { private final ImageUploadService imageUploadService; @PostMapping("/new") + @Operation(summary = "등록", description = "신규 회원 등록") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "등록 성공", + content = {@Content(schema = @Schema(implementation = MemberResponse.class))}), + @ApiResponse(responseCode = "400", description = "잘못된 요청") + }) public MemberResponse create(@RequestBody final MemberRequest memberRequest) { return memberService.join(memberRequest); } @GetMapping("/{memberId}") + @Operation(summary = "조회", description = "기존 회원 조회") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "조회 성공", + content = {@Content(schema = @Schema(implementation = MemberResponse.class))}), + @ApiResponse(responseCode = "404", description = "존재하지 않는 회원", + content = {@Content(schema = @Schema(hidden = true))}) + }) public MemberResponse findMember(@PathVariable final Long memberId) { return memberService.findOne(memberId); } @GetMapping() + @Operation(summary = "조회", description = "기존 회원 조회") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "조회 성공", + content = {@Content(schema = @Schema(implementation = MemberResponse.class))}), + @ApiResponse(responseCode = "404", description = "존재하지 않는 회원", + content = {@Content(schema = @Schema(hidden = true))}) + }) public MemberResponse findMemberQuery(@RequestParam("id") final Long memberId) { return memberService.findOne(memberId); } @GetMapping("/all") + @Operation(summary = "전체 조회", description = "모든 회원 조회") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "조회 성공", + content = {@Content(schema = @Schema(implementation = MemberResponse.class))}) + }) public List findMembers() { return memberService.findAll(); } @PatchMapping(value = "/{memberId}") + @Operation(summary = "수정", description = "기존 회원 수정") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "수정 성공", + content = {@Content(schema = @Schema(implementation = MemberResponse.class))}), + @ApiResponse(responseCode = "404", description = "존재하지 않는 회원", + content = {@Content(schema = @Schema(hidden = true))}) + }) public MemberResponse update(@PathVariable final Long memberId, @RequestBody final UpdateMemberRequest updateMemberRequest) { return memberService.updateById(memberId, updateMemberRequest); } @PatchMapping(value = "/{memberId}/image") + @Operation(summary = "프로필 사진 수정", description = "기존 회원 프로필 사진 수정") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "프로필 사진 수정 성공", + content = {@Content(schema = @Schema(implementation = MemberResponse.class))}), + @ApiResponse(responseCode = "404", description = "존재하지 않는 회원", + content = {@Content(schema = @Schema(hidden = true))}) + }) public MemberResponse updateProfileImage(@PathVariable final Long memberId, @RequestParam("image") MultipartFile multipartFile) throws IOException { String profileImage = imageUploadService.upload(multipartFile); @@ -67,10 +114,18 @@ public MemberResponse updateProfileImage(@PathVariable final Long memberId, } @DeleteMapping("/{memberId}") + @Operation(summary = "삭제", description = "기존 회원 삭제") + @ApiResponses(value = { + @ApiResponse(responseCode = "204", description = "삭제 성공", + content = {@Content(schema = @Schema(implementation = MemberResponse.class))}), + @ApiResponse(responseCode = "404", description = "존재하지 않는 회원", + content = {@Content(schema = @Schema(hidden = true))}) + }) public ResponseEntity delete(@PathVariable final Long memberId) { return memberService.delete(memberId); } + @ResponseStatus(HttpStatus.NOT_FOUND) @ExceptionHandler(EntityNotFoundException.class) public ResponseEntity handleNoSuchElementFoundException(EntityNotFoundException exception) { return ResponseEntity.status(HttpStatus.NOT_FOUND).body(exception.getMessage()); diff --git a/src/main/java/com/cow/cow_mvc_practice/member/controller/dto/request/MemberRequest.java b/src/main/java/com/cow/cow_mvc_practice/member/controller/dto/request/MemberRequest.java index 7bdef03..185d21c 100644 --- a/src/main/java/com/cow/cow_mvc_practice/member/controller/dto/request/MemberRequest.java +++ b/src/main/java/com/cow/cow_mvc_practice/member/controller/dto/request/MemberRequest.java @@ -2,12 +2,20 @@ import com.cow.cow_mvc_practice.member.entity.Member; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Size; import lombok.Getter; import lombok.NoArgsConstructor; @Getter @NoArgsConstructor +@Schema(title = "Member Request : 회원 등록 요청 DTO") public class MemberRequest { + + @NotBlank(message = "회원 이름을 입력해주세요.") + @Size(min = 2, max = 12, message = "사용자 이름은 2글자 이상 12글자 이하로 입력해주세요.") + @Schema(description = "회원 이름") private String name; public Member toEntity() { diff --git a/src/main/java/com/cow/cow_mvc_practice/member/controller/dto/request/UpdateMemberRequest.java b/src/main/java/com/cow/cow_mvc_practice/member/controller/dto/request/UpdateMemberRequest.java index 4edd5c0..16f68e3 100644 --- a/src/main/java/com/cow/cow_mvc_practice/member/controller/dto/request/UpdateMemberRequest.java +++ b/src/main/java/com/cow/cow_mvc_practice/member/controller/dto/request/UpdateMemberRequest.java @@ -1,10 +1,13 @@ package com.cow.cow_mvc_practice.member.controller.dto.request; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Getter; import lombok.NoArgsConstructor; @Getter @NoArgsConstructor +@Schema(title = "Update Member Request : 회원 정보 수정 요청 DTO") public class UpdateMemberRequest { + @Schema(description = "수정하려는 회원 이름") private String name; } diff --git a/src/main/java/com/cow/cow_mvc_practice/member/controller/dto/response/MemberResponse.java b/src/main/java/com/cow/cow_mvc_practice/member/controller/dto/response/MemberResponse.java index a072865..0b2f08d 100644 --- a/src/main/java/com/cow/cow_mvc_practice/member/controller/dto/response/MemberResponse.java +++ b/src/main/java/com/cow/cow_mvc_practice/member/controller/dto/response/MemberResponse.java @@ -5,14 +5,23 @@ import com.cow.cow_mvc_practice.member.entity.Member; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Builder; import lombok.Getter; @Getter +@Schema(title = "Member Response : 회원 결과 DTO") public class MemberResponse { + @Schema(description = "회원 ID") private final Long id; + + @Schema(description = "이름") private final String name; + + @Schema(description = "프로필 이미지 주소") private final String profileImage; + + @Schema(description = "작성한 게시글 제목") private final List posts; @Builder diff --git a/src/main/java/com/cow/cow_mvc_practice/post/controller/PostController.java b/src/main/java/com/cow/cow_mvc_practice/post/controller/PostController.java index 5e27781..7accec2 100644 --- a/src/main/java/com/cow/cow_mvc_practice/post/controller/PostController.java +++ b/src/main/java/com/cow/cow_mvc_practice/post/controller/PostController.java @@ -12,15 +12,24 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestController; +import com.cow.cow_mvc_practice.member.controller.dto.response.MemberResponse; import com.cow.cow_mvc_practice.post.controller.dto.request.PostRequest; import com.cow.cow_mvc_practice.post.controller.dto.response.PostResponse; import com.cow.cow_mvc_practice.post.service.PostService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.persistence.EntityNotFoundException; import lombok.RequiredArgsConstructor; +@Tag(name = "Post", description = "게시글 관련 API") @RestController @RequestMapping("/post") @RequiredArgsConstructor @@ -28,35 +37,78 @@ public class PostController { private final PostService postService; @PostMapping("/new/member/{memberId}") + @Operation(summary = "등록", description = "신규 게시글 등록") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "등록 성공", + content = {@Content(schema = @Schema(implementation = MemberResponse.class))}), + @ApiResponse(responseCode = "400", description = "잘못된 요청", + content = {@Content(schema = @Schema(hidden = true))}), + @ApiResponse(responseCode = "404", description = "존재하지 않는 회원", + content = {@Content(schema = @Schema(hidden = true))}) + }) public PostResponse create(@PathVariable final Long memberId, @RequestBody final PostRequest postRequest) { return postService.join(memberId, postRequest); } @GetMapping("/{postId}") + @Operation(summary = "조회", description = "기존 게시글 조회") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "조회 성공", + content = {@Content(schema = @Schema(implementation = PostResponse.class))}), + @ApiResponse(responseCode = "404", description = "존재하지 않는 게시글", + content = {@Content(schema = @Schema(hidden = true))}) + }) public PostResponse findPost(@PathVariable final Long postId) { return postService.findOne(postId); } @GetMapping() + @Operation(summary = "조회", description = "기존 게시글 조회") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "조회 성공", + content = {@Content(schema = @Schema(implementation = PostResponse.class))}), + @ApiResponse(responseCode = "404", description = "존재하지 않는 게시글", + content = {@Content(schema = @Schema(hidden = true))}) + }) public PostResponse findPostQuery(@RequestParam("id") final Long postId) { return postService.findOne(postId); } @GetMapping("/all") + @Operation(summary = "전체 조회", description = "모든 게시글 조회") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "조회 성공", + content = {@Content(schema = @Schema(implementation = MemberResponse.class))}) + }) public List findPosts() { return postService.findAll(); } @GetMapping("/all/member/{memberId}") + @Operation(summary = "회원의 전체 게시글 조회", description = "특정 회원 ID로 작성된 모든 게시글 조회") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "조회 성공", + content = {@Content(schema = @Schema(implementation = MemberResponse.class))}), + @ApiResponse(responseCode = "404", description = "존재하지 않는 회원", + content = {@Content(schema = @Schema(hidden = true))}) + }) public List findPostsByMember(@PathVariable final Long memberId) { return postService.findAllByMember(memberId); } @DeleteMapping("/{postId}") + @Operation(summary = "삭제", description = "기존 게시글 삭제") + @ApiResponses(value = { + @ApiResponse(responseCode = "204", description = "삭제 성공", + content = {@Content(schema = @Schema(implementation = MemberResponse.class))}), + @ApiResponse(responseCode = "404", description = "존재하지 않는 게시글", + content = {@Content(schema = @Schema(hidden = true))}) + }) public ResponseEntity deletePost(@PathVariable final Long postId) { return postService.delete(postId); } + @ResponseStatus(HttpStatus.NOT_FOUND) @ExceptionHandler(EntityNotFoundException.class) public ResponseEntity handleNoSuchElementFoundException(EntityNotFoundException exception) { return ResponseEntity.status(HttpStatus.NOT_FOUND).body(exception.getMessage()); diff --git a/src/main/java/com/cow/cow_mvc_practice/post/controller/dto/request/PostRequest.java b/src/main/java/com/cow/cow_mvc_practice/post/controller/dto/request/PostRequest.java index 6435141..0a7e7cd 100644 --- a/src/main/java/com/cow/cow_mvc_practice/post/controller/dto/request/PostRequest.java +++ b/src/main/java/com/cow/cow_mvc_practice/post/controller/dto/request/PostRequest.java @@ -1,11 +1,19 @@ package com.cow.cow_mvc_practice.post.controller.dto.request; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; import lombok.Getter; import lombok.NoArgsConstructor; @Getter @NoArgsConstructor +@Schema(title = "Post Request : 게시글 등록 요청 DTO") public class PostRequest { + @NotBlank(message = "게시글 제목을 입력해주세요.") + @Schema(description = "게시글 제목") private String title; + + @NotBlank(message = "게시글 제목을 입력해주세요.") + @Schema(description = "게시글 제목") private String content; } diff --git a/src/main/java/com/cow/cow_mvc_practice/post/controller/dto/request/UpdatePostRequest.java b/src/main/java/com/cow/cow_mvc_practice/post/controller/dto/request/UpdatePostRequest.java deleted file mode 100644 index 6c15051..0000000 --- a/src/main/java/com/cow/cow_mvc_practice/post/controller/dto/request/UpdatePostRequest.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.cow.cow_mvc_practice.post.controller.dto.request; - -import com.cow.cow_mvc_practice.member.entity.Member; - -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Getter -@NoArgsConstructor -public class UpdatePostRequest { - private String title; - private String content; - private Member member; -} diff --git a/src/main/java/com/cow/cow_mvc_practice/post/controller/dto/response/PostResponse.java b/src/main/java/com/cow/cow_mvc_practice/post/controller/dto/response/PostResponse.java index 29099fd..9daa64e 100644 --- a/src/main/java/com/cow/cow_mvc_practice/post/controller/dto/response/PostResponse.java +++ b/src/main/java/com/cow/cow_mvc_practice/post/controller/dto/response/PostResponse.java @@ -8,20 +8,34 @@ import com.cow.cow_mvc_practice.post.entity.Post; import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Builder; import lombok.Getter; @Getter +@Schema(title = "Post Response : 게시글 결과 DTO") public class PostResponse { + + @Schema(description = "게시글 ID") private final Long id; + + @Schema(description = "제목") private final String title; + + @Schema(description = "내용") private final String content; + + @Schema(description = "작성자 ID") private final String memberName; + @Schema(description = "작성 날짜") @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss", timezone = "Asia/Seoul") private final LocalDateTime date; + @Schema(description = "댓글 개수") private final int commentCount; + + @Schema(description = "작성된 댓글 내용") private final List comments; @Builder diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index a6519b0..49e3db9 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -36,3 +36,22 @@ logging: type: descriptor: sql: trace + +springdoc: + swagger-ui: + groups-order: DESC + tags-sorter: alpha + operations-sorter: method + disable-swagger-default-url: true + display-request-duration: true + defaultModelsExpandDepth: 2 + defaultModelExpandDepth: 2 + api-docs: + path: /api-docs + show-actuator: true + default-consumes-media-type: application/json + default-produces-media-type: application/json + writer-with-default-pretty-printer: true + model-and-view-allowed: true + paths-to-match: + - /** From 2ba09f0fc83b1dbcfaf353f6db480169f5f527d3 Mon Sep 17 00:00:00 2001 From: BuildTools Date: Sat, 22 Jun 2024 17:54:46 +0900 Subject: [PATCH 17/18] =?UTF-8?q?refactor=20:=20=EC=9D=91=EB=8B=B5=20DTO?= =?UTF-8?q?=20ResponseEntity=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../member/controller/MemberController.java | 14 ++++---- .../member/service/MemberService.java | 10 +++--- .../member/service/MemberServiceImpl.java | 34 +++++++++++++------ 3 files changed, 35 insertions(+), 23 deletions(-) diff --git a/src/main/java/com/cow/cow_mvc_practice/member/controller/MemberController.java b/src/main/java/com/cow/cow_mvc_practice/member/controller/MemberController.java index dfa3f9d..7eafffb 100644 --- a/src/main/java/com/cow/cow_mvc_practice/member/controller/MemberController.java +++ b/src/main/java/com/cow/cow_mvc_practice/member/controller/MemberController.java @@ -44,11 +44,11 @@ public class MemberController { @PostMapping("/new") @Operation(summary = "등록", description = "신규 회원 등록") @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "등록 성공", + @ApiResponse(responseCode = "201", description = "등록 성공", content = {@Content(schema = @Schema(implementation = MemberResponse.class))}), @ApiResponse(responseCode = "400", description = "잘못된 요청") }) - public MemberResponse create(@RequestBody final MemberRequest memberRequest) { + public ResponseEntity create(@RequestBody final MemberRequest memberRequest) { return memberService.join(memberRequest); } @@ -60,7 +60,7 @@ public MemberResponse create(@RequestBody final MemberRequest memberRequest) { @ApiResponse(responseCode = "404", description = "존재하지 않는 회원", content = {@Content(schema = @Schema(hidden = true))}) }) - public MemberResponse findMember(@PathVariable final Long memberId) { + public ResponseEntity findMember(@PathVariable final Long memberId) { return memberService.findOne(memberId); } @@ -72,7 +72,7 @@ public MemberResponse findMember(@PathVariable final Long memberId) { @ApiResponse(responseCode = "404", description = "존재하지 않는 회원", content = {@Content(schema = @Schema(hidden = true))}) }) - public MemberResponse findMemberQuery(@RequestParam("id") final Long memberId) { + public ResponseEntity findMemberQuery(@RequestParam("id") final Long memberId) { return memberService.findOne(memberId); } @@ -82,7 +82,7 @@ public MemberResponse findMemberQuery(@RequestParam("id") final Long memberId) { @ApiResponse(responseCode = "200", description = "조회 성공", content = {@Content(schema = @Schema(implementation = MemberResponse.class))}) }) - public List findMembers() { + public ResponseEntity> findMembers() { return memberService.findAll(); } @@ -94,7 +94,7 @@ public List findMembers() { @ApiResponse(responseCode = "404", description = "존재하지 않는 회원", content = {@Content(schema = @Schema(hidden = true))}) }) - public MemberResponse update(@PathVariable final Long memberId, + public ResponseEntity update(@PathVariable final Long memberId, @RequestBody final UpdateMemberRequest updateMemberRequest) { return memberService.updateById(memberId, updateMemberRequest); } @@ -107,7 +107,7 @@ public MemberResponse update(@PathVariable final Long memberId, @ApiResponse(responseCode = "404", description = "존재하지 않는 회원", content = {@Content(schema = @Schema(hidden = true))}) }) - public MemberResponse updateProfileImage(@PathVariable final Long memberId, + public ResponseEntity updateProfileImage(@PathVariable final Long memberId, @RequestParam("image") MultipartFile multipartFile) throws IOException { String profileImage = imageUploadService.upload(multipartFile); return memberService.updateImageById(memberId, profileImage); diff --git a/src/main/java/com/cow/cow_mvc_practice/member/service/MemberService.java b/src/main/java/com/cow/cow_mvc_practice/member/service/MemberService.java index 18af7cc..1bf5948 100644 --- a/src/main/java/com/cow/cow_mvc_practice/member/service/MemberService.java +++ b/src/main/java/com/cow/cow_mvc_practice/member/service/MemberService.java @@ -9,15 +9,15 @@ import com.cow.cow_mvc_practice.member.controller.dto.response.MemberResponse; public interface MemberService { - MemberResponse findOne(Long memberId); + ResponseEntity findOne(Long memberId); - MemberResponse join(MemberRequest memberRequest); + ResponseEntity join(MemberRequest memberRequest); - List findAll(); + ResponseEntity> findAll(); ResponseEntity delete(Long memberId); - MemberResponse updateById(Long memberId, UpdateMemberRequest updateMemberRequest); + ResponseEntity updateById(Long memberId, UpdateMemberRequest updateMemberRequest); - MemberResponse updateImageById(Long memberId, String profileImage); + ResponseEntity updateImageById(Long memberId, String profileImage); } diff --git a/src/main/java/com/cow/cow_mvc_practice/member/service/MemberServiceImpl.java b/src/main/java/com/cow/cow_mvc_practice/member/service/MemberServiceImpl.java index 3c82125..41572e9 100644 --- a/src/main/java/com/cow/cow_mvc_practice/member/service/MemberServiceImpl.java +++ b/src/main/java/com/cow/cow_mvc_practice/member/service/MemberServiceImpl.java @@ -5,6 +5,7 @@ import java.util.stream.Collectors; import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -25,27 +26,34 @@ public class MemberServiceImpl implements MemberService { private final MemberJPARepository memberRepository; @Override - public MemberResponse join(MemberRequest memberRequest) { + public ResponseEntity join(MemberRequest memberRequest) { Member member = memberRequest.toEntity(); memberRepository.save(member); - return MemberResponse.from(member); + return ResponseEntity.status(HttpStatus.CREATED) + .contentType(MediaType.APPLICATION_JSON) + .body(MemberResponse.from(member)); } @Transactional(readOnly = true) @Override - public MemberResponse findOne(Long memberId) { + public ResponseEntity findOne(Long memberId) { Member member = memberRepository.findById(memberId) .orElseThrow(() -> new EntityNotFoundException("[Error] 사용자를 찾을 수 없습니다.")); - return MemberResponse.from(member); + return ResponseEntity.status(HttpStatus.OK) + .contentType(MediaType.APPLICATION_JSON) + .body(MemberResponse.from(member)); } @Transactional(readOnly = true) @Override - public List findAll() { + public ResponseEntity> findAll() { List members = memberRepository.findAll(); - return members.stream() + List memberResponses = members.stream() .map(MemberResponse::from) .collect(Collectors.toList()); + return ResponseEntity.status(HttpStatus.OK) + .contentType(MediaType.APPLICATION_JSON) + .body(memberResponses); } @Override @@ -55,24 +63,28 @@ public ResponseEntity delete(Long memberId) { throw new EntityNotFoundException("[Error] 사용자를 찾을 수 없습니다."); } memberRepository.deleteById(memberId); - return new ResponseEntity<>(null, null, HttpStatus.NO_CONTENT); + return ResponseEntity.status(HttpStatus.NO_CONTENT).build(); } @Override - public MemberResponse updateById(Long memberId, UpdateMemberRequest updateMemberRequest) { + public ResponseEntity updateById(Long memberId, UpdateMemberRequest updateMemberRequest) { Member member = memberRepository.findById(memberId) .orElseThrow(() -> new EntityNotFoundException("[Error] 사용자를 찾을 수 없습니다.")); String name = Optional.ofNullable(updateMemberRequest.getName()).orElse(member.getName()); member.updateMemberName(name); - return MemberResponse.from(member); + return ResponseEntity.status(HttpStatus.OK) + .contentType(MediaType.APPLICATION_JSON) + .body(MemberResponse.from(member)); } @Override - public MemberResponse updateImageById(Long memberId, String profileImage) { + public ResponseEntity updateImageById(Long memberId, String profileImage) { Member member = memberRepository.findById(memberId) .orElseThrow(() -> new EntityNotFoundException("[Error] 사용자를 찾을 수 없습니다.")); profileImage = Optional.ofNullable(profileImage).orElseThrow(IllegalArgumentException::new); member.updateProfileImage(profileImage); - return MemberResponse.from(member); + return ResponseEntity.status(HttpStatus.OK) + .contentType(MediaType.APPLICATION_JSON) + .body(MemberResponse.from(member)); } } From 69c840ca8b9f9815c2b0be85826083d5ad537b51 Mon Sep 17 00:00:00 2001 From: BuildTools Date: Thu, 27 Jun 2024 14:42:16 +0900 Subject: [PATCH 18/18] =?UTF-8?q?test=20:=20=ED=9A=8C=EC=9B=90=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 2 + .../member/controller/MemberController.java | 16 +- .../controller/dto/request/MemberRequest.java | 3 + .../dto/request/UpdateMemberRequest.java | 4 + .../member/repository/MemberRepository.java | 15 -- .../repository/MemberRepositoryImpl.java | 33 --- .../member/service/MemberServiceImpl.java | 7 +- src/main/resources/application.yml | 2 +- .../CowMvcPracticeApplicationTests.java | 11 + .../controller/MemberControllerTest.java | 250 ++++++++++++++++++ .../repository/MemberRepositoryTest.java | 82 ++++++ .../member/service/MemberServiceTest.java | 142 ++++++++++ 12 files changed, 510 insertions(+), 57 deletions(-) delete mode 100644 src/main/java/com/cow/cow_mvc_practice/member/repository/MemberRepository.java delete mode 100644 src/main/java/com/cow/cow_mvc_practice/member/repository/MemberRepositoryImpl.java create mode 100644 src/test/java/com/cow/cow_mvc_practice/CowMvcPracticeApplicationTests.java create mode 100644 src/test/java/com/cow/cow_mvc_practice/member/controller/MemberControllerTest.java create mode 100644 src/test/java/com/cow/cow_mvc_practice/member/repository/MemberRepositoryTest.java create mode 100644 src/test/java/com/cow/cow_mvc_practice/member/service/MemberServiceTest.java diff --git a/build.gradle b/build.gradle index 233c1a5..437296e 100644 --- a/build.gradle +++ b/build.gradle @@ -29,11 +29,13 @@ dependencies { implementation 'mysql:mysql-connector-java:8.0.32' implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-web' + implementation 'org.springframework.boot:spring-boot-starter-validation' testImplementation 'junit:junit:4.13.1' compileOnly 'org.projectlombok:lombok' developmentOnly 'org.springframework.boot:spring-boot-docker-compose' annotationProcessor 'org.projectlombok:lombok' testImplementation 'org.springframework.boot:spring-boot-starter-test' + testImplementation 'org.springframework.boot:spring-boot-starter-data-jpa' testImplementation 'org.testcontainers:testcontainers' testImplementation 'org.testcontainers:junit-jupiter:1.19.7' // Using the same version as Testcontainers testImplementation "org.testcontainers:mysql:1.19.7" // Using the same version as Testcontainers diff --git a/src/main/java/com/cow/cow_mvc_practice/member/controller/MemberController.java b/src/main/java/com/cow/cow_mvc_practice/member/controller/MemberController.java index 7eafffb..c630b9e 100644 --- a/src/main/java/com/cow/cow_mvc_practice/member/controller/MemberController.java +++ b/src/main/java/com/cow/cow_mvc_practice/member/controller/MemberController.java @@ -5,6 +5,7 @@ import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.GetMapping; @@ -31,10 +32,11 @@ import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.persistence.EntityNotFoundException; +import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; -@Tag(name = "Member", description = "회원 관련 API") @RestController +@Tag(name = "Member", description = "회원 관련 API") @RequestMapping("/member") @RequiredArgsConstructor public class MemberController { @@ -48,7 +50,7 @@ public class MemberController { content = {@Content(schema = @Schema(implementation = MemberResponse.class))}), @ApiResponse(responseCode = "400", description = "잘못된 요청") }) - public ResponseEntity create(@RequestBody final MemberRequest memberRequest) { + public ResponseEntity create(@Valid @RequestBody final MemberRequest memberRequest) { return memberService.join(memberRequest); } @@ -95,7 +97,7 @@ public ResponseEntity> findMembers() { content = {@Content(schema = @Schema(hidden = true))}) }) public ResponseEntity update(@PathVariable final Long memberId, - @RequestBody final UpdateMemberRequest updateMemberRequest) { + @Valid @RequestBody final UpdateMemberRequest updateMemberRequest) { return memberService.updateById(memberId, updateMemberRequest); } @@ -127,7 +129,13 @@ public ResponseEntity delete(@PathVariable final Long memberId) { @ResponseStatus(HttpStatus.NOT_FOUND) @ExceptionHandler(EntityNotFoundException.class) - public ResponseEntity handleNoSuchElementFoundException(EntityNotFoundException exception) { + public ResponseEntity handleEntityNotFoundException(EntityNotFoundException exception) { return ResponseEntity.status(HttpStatus.NOT_FOUND).body(exception.getMessage()); } + + @ResponseStatus(HttpStatus.BAD_REQUEST) + @ExceptionHandler(MethodArgumentNotValidException.class) + public ResponseEntity handleMethodArgumentNotValidException(MethodArgumentNotValidException exception) { + return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("잘못된 요청입니다."); + } } diff --git a/src/main/java/com/cow/cow_mvc_practice/member/controller/dto/request/MemberRequest.java b/src/main/java/com/cow/cow_mvc_practice/member/controller/dto/request/MemberRequest.java index 185d21c..2ba0ae8 100644 --- a/src/main/java/com/cow/cow_mvc_practice/member/controller/dto/request/MemberRequest.java +++ b/src/main/java/com/cow/cow_mvc_practice/member/controller/dto/request/MemberRequest.java @@ -5,17 +5,20 @@ import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.Size; +import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; @Getter @NoArgsConstructor +@AllArgsConstructor @Schema(title = "Member Request : 회원 등록 요청 DTO") public class MemberRequest { @NotBlank(message = "회원 이름을 입력해주세요.") @Size(min = 2, max = 12, message = "사용자 이름은 2글자 이상 12글자 이하로 입력해주세요.") @Schema(description = "회원 이름") + // @NotNull private String name; public Member toEntity() { diff --git a/src/main/java/com/cow/cow_mvc_practice/member/controller/dto/request/UpdateMemberRequest.java b/src/main/java/com/cow/cow_mvc_practice/member/controller/dto/request/UpdateMemberRequest.java index 16f68e3..1b7ce54 100644 --- a/src/main/java/com/cow/cow_mvc_practice/member/controller/dto/request/UpdateMemberRequest.java +++ b/src/main/java/com/cow/cow_mvc_practice/member/controller/dto/request/UpdateMemberRequest.java @@ -1,13 +1,17 @@ package com.cow.cow_mvc_practice.member.controller.dto.request; import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; @Getter @NoArgsConstructor +@AllArgsConstructor @Schema(title = "Update Member Request : 회원 정보 수정 요청 DTO") public class UpdateMemberRequest { + @NotBlank(message = "회원 이름을 입력해주세요.") @Schema(description = "수정하려는 회원 이름") private String name; } diff --git a/src/main/java/com/cow/cow_mvc_practice/member/repository/MemberRepository.java b/src/main/java/com/cow/cow_mvc_practice/member/repository/MemberRepository.java deleted file mode 100644 index b9cd48b..0000000 --- a/src/main/java/com/cow/cow_mvc_practice/member/repository/MemberRepository.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.cow.cow_mvc_practice.member.repository; - -import java.util.List; -import java.util.Optional; - -import com.cow.cow_mvc_practice.member.entity.Member; - -public interface MemberRepository { - - void save(Member member); - - Optional findById(Long memberId); - - Optional> findAll(); -} diff --git a/src/main/java/com/cow/cow_mvc_practice/member/repository/MemberRepositoryImpl.java b/src/main/java/com/cow/cow_mvc_practice/member/repository/MemberRepositoryImpl.java deleted file mode 100644 index 03125fe..0000000 --- a/src/main/java/com/cow/cow_mvc_practice/member/repository/MemberRepositoryImpl.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.cow.cow_mvc_practice.member.repository; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; - -import org.springframework.stereotype.Repository; - -import com.cow.cow_mvc_practice.member.entity.Member; - -@Repository -public class MemberRepositoryImpl implements MemberRepository { - /** - * 원래라면 HashMap이 아닌, concurrentHashMap이 적합함. HashMap은 멀티 쓰레드 환경에서 사용할 수 없기 때문.(동시성 이슈) - */ - private static final Map store = new HashMap<>(); - - @Override - public void save(Member member) { - store.put(member.getId(), member); - } - - @Override - public Optional findById(Long memberId) { - return Optional.ofNullable(store.get(memberId)); - } - - @Override - public Optional> findAll() { - return Optional.of((List)store.values()); - } -} diff --git a/src/main/java/com/cow/cow_mvc_practice/member/service/MemberServiceImpl.java b/src/main/java/com/cow/cow_mvc_practice/member/service/MemberServiceImpl.java index 41572e9..d281fb7 100644 --- a/src/main/java/com/cow/cow_mvc_practice/member/service/MemberServiceImpl.java +++ b/src/main/java/com/cow/cow_mvc_practice/member/service/MemberServiceImpl.java @@ -28,10 +28,10 @@ public class MemberServiceImpl implements MemberService { @Override public ResponseEntity join(MemberRequest memberRequest) { Member member = memberRequest.toEntity(); - memberRepository.save(member); + Member savedMember = memberRepository.save(member); return ResponseEntity.status(HttpStatus.CREATED) .contentType(MediaType.APPLICATION_JSON) - .body(MemberResponse.from(member)); + .body(MemberResponse.from(savedMember)); } @Transactional(readOnly = true) @@ -70,8 +70,7 @@ public ResponseEntity delete(Long memberId) { public ResponseEntity updateById(Long memberId, UpdateMemberRequest updateMemberRequest) { Member member = memberRepository.findById(memberId) .orElseThrow(() -> new EntityNotFoundException("[Error] 사용자를 찾을 수 없습니다.")); - String name = Optional.ofNullable(updateMemberRequest.getName()).orElse(member.getName()); - member.updateMemberName(name); + member.updateMemberName(updateMemberRequest.getName()); return ResponseEntity.status(HttpStatus.OK) .contentType(MediaType.APPLICATION_JSON) .body(MemberResponse.from(member)); diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 49e3db9..4da57c5 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -6,7 +6,7 @@ spring: jpa: open-in-view: true hibernate: - ddl-auto: validate + ddl-auto: create show-sql: true properties: hibernate: diff --git a/src/test/java/com/cow/cow_mvc_practice/CowMvcPracticeApplicationTests.java b/src/test/java/com/cow/cow_mvc_practice/CowMvcPracticeApplicationTests.java new file mode 100644 index 0000000..cb7ab74 --- /dev/null +++ b/src/test/java/com/cow/cow_mvc_practice/CowMvcPracticeApplicationTests.java @@ -0,0 +1,11 @@ +package com.cow.cow_mvc_practice; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +public class CowMvcPracticeApplicationTests { + @Test + void contextLoads() { + } +} diff --git a/src/test/java/com/cow/cow_mvc_practice/member/controller/MemberControllerTest.java b/src/test/java/com/cow/cow_mvc_practice/member/controller/MemberControllerTest.java new file mode 100644 index 0000000..f9aecd1 --- /dev/null +++ b/src/test/java/com/cow/cow_mvc_practice/member/controller/MemberControllerTest.java @@ -0,0 +1,250 @@ +package com.cow.cow_mvc_practice.member.controller; + +import static org.mockito.BDDMockito.*; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.mock.web.MockMultipartFile; +import org.springframework.test.web.servlet.MockMvc; +import org.testcontainers.shaded.com.fasterxml.jackson.databind.ObjectMapper; + +import com.cow.cow_mvc_practice.Image.service.ImageUploadServiceImpl; +import com.cow.cow_mvc_practice.member.controller.dto.request.MemberRequest; +import com.cow.cow_mvc_practice.member.controller.dto.request.UpdateMemberRequest; +import com.cow.cow_mvc_practice.member.controller.dto.response.MemberResponse; +import com.cow.cow_mvc_practice.member.entity.Member; +import com.cow.cow_mvc_practice.member.service.MemberServiceImpl; + +import jakarta.persistence.EntityNotFoundException; + +@WebMvcTest(MemberController.class) +public class MemberControllerTest { + @Autowired + MockMvc mockMvc; + + @MockBean + MemberServiceImpl memberService; + @MockBean + ImageUploadServiceImpl imageUploadService; + + @Test + @DisplayName("회원 조회 테스트") + void getMemberTest() throws Exception { + Long memberId = 123L; + + Member member = Member.builder().id(memberId).name("Test Member").build(); + given(memberService.findOne(memberId)).willReturn( + ResponseEntity.status(HttpStatus.OK) + .contentType(MediaType.APPLICATION_JSON) + .body(MemberResponse.from(member))); + + mockMvc.perform( + get("/member/" + memberId)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id").exists()) + .andExpect(jsonPath("$.name").exists()) + .andExpect(jsonPath("$.profileImage").exists()) + .andExpect(jsonPath("$.posts").exists()) + .andDo(print()); + + verify(memberService).findOne(memberId); + } + + @Test + @DisplayName("회원 조회 파라미터 테스트") + void getMemberParameterTest() throws Exception { + Long memberId = 123L; + + Member member = Member.builder().id(memberId).name("Test Member").build(); + given(memberService.findOne(memberId)).willReturn( + ResponseEntity.status(HttpStatus.OK) + .contentType(MediaType.APPLICATION_JSON) + .body(MemberResponse.from(member))); + + mockMvc.perform( + get("/member?id=" + memberId)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id").exists()) + .andExpect(jsonPath("$.name").exists()) + .andExpect(jsonPath("$.profileImage").exists()) + .andExpect(jsonPath("$.posts").exists()) + .andDo(print()); + + verify(memberService).findOne(memberId); + } + + @Test + @DisplayName("존재하지 않는 회원 조회 테스트") + void getMemberExceptionTest() throws Exception { + Long memberId = 123L; + given(memberService.findOne(memberId)).willThrow(new EntityNotFoundException("[Error] 사용자를 찾을 수 없습니다.")); + + mockMvc.perform( + get("/member/" + memberId)) + .andExpect(status().isNotFound()) + .andDo(print()); + + verify(memberService).findOne(memberId); + } + + @Test + @DisplayName("회원 전체 조회 테스트") + void getAllMemberTest() throws Exception { + List memberResponses = new ArrayList<>(); + memberResponses.add(MemberResponse.from(Member.builder().id(123L).name("Test Member").build())); + given(memberService.findAll()).willReturn( + ResponseEntity.status(HttpStatus.OK) + .contentType(MediaType.APPLICATION_JSON) + .body(memberResponses)); + + mockMvc.perform( + get("/member/all")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$..id").exists()) + .andExpect(jsonPath("$..name").exists()) + .andExpect(jsonPath("$..profileImage").exists()) + .andExpect(jsonPath("$..posts").exists()) + .andDo(print()); + + verify(memberService).findAll(); + } + + @Test + @DisplayName("회원 등록 테스트") + void createMemberTest() throws Exception { + MemberRequest memberRequest = new MemberRequest("Test Member"); + Member member = Member.builder().id(123L).name(memberRequest.getName()).build(); + + given(memberService.join(any())).willReturn( + ResponseEntity.status(HttpStatus.CREATED) + .contentType(MediaType.APPLICATION_JSON) + .body(MemberResponse.from(member)) + ); + + String json = new ObjectMapper().writeValueAsString(memberRequest); + + mockMvc.perform( + post("/member/new") + .content(json) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isCreated()) + .andExpect(jsonPath("$.id").exists()) + .andExpect(jsonPath("$.name").exists()) + .andExpect(jsonPath("$.profileImage").exists()) + .andExpect(jsonPath("$.posts").exists()) + .andDo(print()); + + verify(memberService).join(any()); + } + + @Test + @DisplayName("잘못된 회원 등록 테스트") + void createMemberExceptionTest() throws Exception { + MemberRequest memberRequest = new MemberRequest(null); + + given(memberService.join(any())).willThrow(new EntityNotFoundException("[Error] 사용자를 찾을 수 없습니다.")); + + String json = new ObjectMapper().writeValueAsString(memberRequest); + + mockMvc.perform( + post("/member/new") + .content(json) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isBadRequest()) + .andDo(print()); + + verifyNoInteractions(memberService); + } + + @Test + @DisplayName("회원 삭제 테스트") + void deleteMemberTest() throws Exception { + Long memberId = 123L; + + given(memberService.delete(memberId)).willReturn( + ResponseEntity.noContent().build()); + + mockMvc.perform( + delete("/member/" + memberId)) + .andExpect(status().isNoContent()) + .andDo(print()); + + verify(memberService).delete(memberId); + } + + @Test + @DisplayName("회원 수정 테스트") + void updateMemberTest() throws Exception { + Long memberId = 123L; + UpdateMemberRequest memberRequest = new UpdateMemberRequest("Update Member"); + Member member = Member.builder().id(memberId).name(memberRequest.getName()).build(); + + given(memberService.updateById(any(), any())).willReturn( + ResponseEntity.status(HttpStatus.OK) + .contentType(MediaType.APPLICATION_JSON) + .body(MemberResponse.from(member))); + + String json = new ObjectMapper().writeValueAsString(memberRequest); + + mockMvc.perform( + patch("/member/" + memberId) + .content(json) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id").exists()) + .andExpect(jsonPath("$.name").exists()) + .andExpect(jsonPath("$.profileImage").exists()) + .andExpect(jsonPath("$.posts").exists()) + .andDo(print()); + + verify(memberService).updateById(any(), any()); + } + + @Test + @DisplayName("회원 프로필 사진 수정 테스트") + void updateMemberImageTest() throws Exception { + Long memberId = 123L; + Member member = Member.builder().id(memberId).name("Test Member").build(); + MockMultipartFile imageFile = new MockMultipartFile( + "image", + "profile.png", + MediaType.IMAGE_PNG_VALUE, + "profile".getBytes() + ); + String imageLink = imageFile.getOriginalFilename() + "_Image_Link"; + given(imageUploadService.upload(any())).willReturn( + imageLink); + + member.updateProfileImage(imageLink); + given(memberService.updateImageById(any(), any())).willReturn( + ResponseEntity.status(HttpStatus.OK) + .contentType(MediaType.APPLICATION_JSON) + .body(MemberResponse.from(member))); + + mockMvc.perform( + multipart(HttpMethod.PATCH, "/member/" + memberId + "/image") + .file(imageFile)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id").exists()) + .andExpect(jsonPath("$.name").exists()) + .andExpect(jsonPath("$.profileImage").exists()) + .andExpect(jsonPath("$.posts").exists()) + .andDo(print()); + + verify(imageUploadService).upload(any()); + verify(memberService).updateImageById(any(), any()); + } +} diff --git a/src/test/java/com/cow/cow_mvc_practice/member/repository/MemberRepositoryTest.java b/src/test/java/com/cow/cow_mvc_practice/member/repository/MemberRepositoryTest.java new file mode 100644 index 0000000..f3093cb --- /dev/null +++ b/src/test/java/com/cow/cow_mvc_practice/member/repository/MemberRepositoryTest.java @@ -0,0 +1,82 @@ +package com.cow.cow_mvc_practice.member.repository; + +import java.util.List; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; + +import com.cow.cow_mvc_practice.member.entity.Member; + +@DataJpaTest +@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) +public class MemberRepositoryTest { + @Autowired + MemberJPARepository memberRepository; + + @Test + @DisplayName("회원 저장하기") + void saveMember() { + Member savedMember = memberRepository.save(Member.from("Test Member")); + Assertions.assertThat(savedMember.getName()).isEqualTo("Test Member"); + Assertions.assertThat(savedMember.getProfileImage()) + .isEqualTo("https://mycowpracticebucket.s3.ap-northeast-2.amazonaws.com/anonymous.png"); + Assertions.assertThat(savedMember.getPosts().size()).isEqualTo(0); + } + + @Test + @DisplayName("회원 불러오기") + void getMember() { + Member savedMember = memberRepository.save(Member.from("Test Member")); + + Member findMember = memberRepository.findById(savedMember.getId()).orElseThrow(); + Assertions.assertThat(savedMember).isEqualTo(findMember); + } + + @Test + @DisplayName("모든 회원 불러오기") + void getAllMembers() { + Member member1 = Member.from("Test Member 1"); + memberRepository.save(member1); + Member member2 = Member.from("Test Member 2"); + memberRepository.save(member2); + Member member3 = Member.from("Test Member 3"); + memberRepository.save(member3); + + memberRepository.findAll(); + List findMembers = memberRepository.findAll(); + + Assertions.assertThat(findMembers.size()).isEqualTo(3); + } + + @Test + @DisplayName("회원 삭제하기") + void deleteMember() { + Member member = Member.from("Test Member"); + Member savedMember = memberRepository.save(member); + + boolean isExistBefore = memberRepository.existsById(savedMember.getId()); + memberRepository.deleteById(savedMember.getId()); + boolean isExistAfter = memberRepository.existsById(savedMember.getId()); + + Assertions.assertThat(isExistBefore).isEqualTo(true); + Assertions.assertThat(isExistAfter).isEqualTo(false); + } + + @Test + @DisplayName("회원 수정하기") + void updateMember() { + Member member = Member.from("Test Member"); + Member savedMember = memberRepository.save(member); + + savedMember.updateMemberName("Update Member"); + savedMember.updateProfileImage("Update_Image_Link"); + + Member findMember = memberRepository.findById(savedMember.getId()).orElseThrow(); + Assertions.assertThat(findMember.getName()).isEqualTo("Update Member"); + Assertions.assertThat(findMember.getProfileImage()).isEqualTo("Update_Image_Link"); + } +} diff --git a/src/test/java/com/cow/cow_mvc_practice/member/service/MemberServiceTest.java b/src/test/java/com/cow/cow_mvc_practice/member/service/MemberServiceTest.java new file mode 100644 index 0000000..291dc83 --- /dev/null +++ b/src/test/java/com/cow/cow_mvc_practice/member/service/MemberServiceTest.java @@ -0,0 +1,142 @@ +package com.cow.cow_mvc_practice.member.service; + +import static org.mockito.BDDMockito.*; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; +import org.springframework.http.ResponseEntity; + +import com.cow.cow_mvc_practice.member.controller.dto.request.MemberRequest; +import com.cow.cow_mvc_practice.member.controller.dto.request.UpdateMemberRequest; +import com.cow.cow_mvc_practice.member.controller.dto.response.MemberResponse; +import com.cow.cow_mvc_practice.member.entity.Member; +import com.cow.cow_mvc_practice.member.repository.MemberJPARepository; + +@ExtendWith(MockitoExtension.class) +public class MemberServiceTest { + @InjectMocks + MemberServiceImpl memberService; + + @Mock + MemberJPARepository memberRepository; + + @Test + @DisplayName("회원 불러오기") + public void getMember() { + Member member = Member.builder().id(1L).name("Test Member").build(); + + given(memberRepository.findById(member.getId())).willReturn(Optional.of(member)); + + ResponseEntity memberResponseEntity = memberService.findOne(member.getId()); + HttpStatusCode status = memberResponseEntity.getStatusCode(); + MemberResponse memberResponse = memberResponseEntity.getBody(); + Assertions.assertThat(status).isEqualTo(HttpStatus.OK); + checkMember(memberResponse, member); + } + + @Test + @DisplayName("회원 전체 불러오기") + public void getAllMember() { + List members = new ArrayList<>(); + Member member1 = Member.builder().id(1L).name("Test Member1").build(); + Member member2 = Member.builder().id(2L).name("Test Member2").build(); + Member member3 = Member.builder().id(3L).name("Test Member3").build(); + members.add(member1); + members.add(member2); + members.add(member3); + + given(memberRepository.findAll()).willReturn(members); + + ResponseEntity> memberResponseEntity = memberService.findAll(); + HttpStatusCode status = memberResponseEntity.getStatusCode(); + List memberResponses = memberResponseEntity.getBody(); + Assertions.assertThat(status).isEqualTo(HttpStatus.OK); + Assertions.assertThat(memberResponses).isNotNull(); + checkMember(memberResponses.get(0), member1); + checkMember(memberResponses.get(1), member2); + checkMember(memberResponses.get(2), member3); + } + + @Test + @DisplayName("회원 저장") + public void saveMember() { + MemberRequest request = new MemberRequest("Test Member"); + Long memberId = 1L; + Member member = Member.builder().id(memberId).name(request.getName()).build(); + + given(memberRepository.save(any())).willReturn(member); + + ResponseEntity memberResponseEntity = memberService.join(request); + HttpStatusCode status = memberResponseEntity.getStatusCode(); + MemberResponse memberResponse = memberResponseEntity.getBody(); + Assertions.assertThat(status).isEqualTo(HttpStatus.CREATED); + checkMember(memberResponse, member); + } + + @Test + @DisplayName("회원 수정") + public void updateMember() { + MemberRequest request = new MemberRequest("Test Member"); + UpdateMemberRequest updateRequest = new UpdateMemberRequest("Update Member"); + Long memberId = 1L; + Member member = Member.builder().id(memberId).name(request.getName()).build(); + Member updateMember = Member.builder().id(memberId).name(updateRequest.getName()).build(); + + given(memberRepository.findById(memberId)).willReturn(Optional.of(member)); + + ResponseEntity memberResponseEntity = memberService.updateById(memberId, updateRequest); + HttpStatusCode status = memberResponseEntity.getStatusCode(); + MemberResponse memberResponse = memberResponseEntity.getBody(); + Assertions.assertThat(status).isEqualTo(HttpStatus.OK); + checkMember(memberResponse, updateMember); + } + + @Test + @DisplayName("회원 이미지 수정") + public void updateMemberImage() { + MemberRequest request = new MemberRequest("Test Member"); + String imageLink = "Profile_Image_Link"; + Long memberId = 1L; + Member member = Member.builder().id(memberId).name(request.getName()).build(); + + given(memberRepository.findById(memberId)).willReturn(Optional.of(member)); + + ResponseEntity memberResponseEntity = memberService.updateImageById(memberId, imageLink); + HttpStatusCode status = memberResponseEntity.getStatusCode(); + MemberResponse memberResponse = memberResponseEntity.getBody(); + Assertions.assertThat(status).isEqualTo(HttpStatus.OK); + checkMember(memberResponse, member); + Assertions.assertThat(member.getProfileImage()).isEqualTo(imageLink); + } + + @Test + @DisplayName("회원 삭제") + public void deleteMember() { + Long memberId = 1L; + + given(memberRepository.existsById(memberId)).willReturn(true); + + ResponseEntity memberResponseEntity = memberService.delete(memberId); + HttpStatusCode status = memberResponseEntity.getStatusCode(); + Assertions.assertThat(status).isEqualTo(HttpStatus.NO_CONTENT); + } + + private void checkMember(MemberResponse memberResponse, Member member) { + Assertions.assertThat(memberResponse).isNotNull(); + Assertions.assertThat(member.getId()).isEqualTo(memberResponse.getId()); + Assertions.assertThat(member.getName()).isEqualTo(memberResponse.getName()); + Assertions.assertThat(member.getPosts().size()).isEqualTo(memberResponse.getPosts().size()); + Assertions.assertThat(member.getProfileImage()).isEqualTo(memberResponse.getProfileImage()); + } +}