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..3128be1 --- /dev/null +++ b/src/main/java/com/cow/cow_mvc_practice/comment/controller/CommentController.java @@ -0,0 +1,22 @@ +package com.cow.cow_mvc_practice.comment.controller; + +import com.cow.cow_mvc_practice.comment.dto.request.CreateCommentRequest; +import com.cow.cow_mvc_practice.comment.dto.response.CreateCommentResponse; +import com.cow.cow_mvc_practice.comment.service.CommentService; +import lombok.RequiredArgsConstructor; +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.RestController; + +@RestController +@RequestMapping("/comments") +@RequiredArgsConstructor +public class CommentController { + private final CommentService commentService; + + @PostMapping("/new") + public CreateCommentResponse create(@RequestBody final CreateCommentRequest createCommentRequest) { + return commentService.createComment(createCommentRequest); + } +} diff --git a/src/main/java/com/cow/cow_mvc_practice/comment/dto/request/CreateCommentRequest.java b/src/main/java/com/cow/cow_mvc_practice/comment/dto/request/CreateCommentRequest.java new file mode 100644 index 0000000..0e873bf --- /dev/null +++ b/src/main/java/com/cow/cow_mvc_practice/comment/dto/request/CreateCommentRequest.java @@ -0,0 +1,19 @@ +package com.cow.cow_mvc_practice.comment.dto.request; + +import com.cow.cow_mvc_practice.comment.entity.Comment; +import lombok.Builder; +import lombok.Getter; + +@Getter +public class CreateCommentRequest { + private Long memberId; + private Long postId; + private String content; + + public static Comment toEntity(String content) { + return Comment.builder() + .content(content) + .build(); + } + +} diff --git a/src/main/java/com/cow/cow_mvc_practice/comment/dto/response/CreateCommentResponse.java b/src/main/java/com/cow/cow_mvc_practice/comment/dto/response/CreateCommentResponse.java new file mode 100644 index 0000000..b3b5c39 --- /dev/null +++ b/src/main/java/com/cow/cow_mvc_practice/comment/dto/response/CreateCommentResponse.java @@ -0,0 +1,24 @@ +package com.cow.cow_mvc_practice.comment.dto.response; + +import com.cow.cow_mvc_practice.comment.entity.Comment; +import lombok.Builder; +import lombok.Getter; + +@Getter +public class CreateCommentResponse { + private final Long id; + private final String content; + + @Builder + private CreateCommentResponse(Long id, String content) { + this.id = id; + this.content = content; + } + + public static CreateCommentResponse from(final Comment comment) { + return CreateCommentResponse.builder() + .id(comment.getId()) + .content(comment.getContent()) + .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..b759b19 --- /dev/null +++ b/src/main/java/com/cow/cow_mvc_practice/comment/entity/Comment.java @@ -0,0 +1,54 @@ +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.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; +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, final Post post, final Member member) { + this.id = id; + this.content = content; + this.post = post; + this.member = member; + } + + public static Comment of(final String content, final Post post, final Member member) { + return Comment.builder() + .content(content) + .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..a9aab23 --- /dev/null +++ b/src/main/java/com/cow/cow_mvc_practice/comment/repository/CommentJPARepository.java @@ -0,0 +1,8 @@ +package com.cow.cow_mvc_practice.comment.repository; + +import com.cow.cow_mvc_practice.comment.entity.Comment; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface CommentJPARepository extends JpaRepository { + +} 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..5c38d90 --- /dev/null +++ b/src/main/java/com/cow/cow_mvc_practice/comment/service/CommentService.java @@ -0,0 +1,14 @@ +package com.cow.cow_mvc_practice.comment.service; + +import com.cow.cow_mvc_practice.comment.dto.request.CreateCommentRequest; +import com.cow.cow_mvc_practice.comment.dto.response.CreateCommentResponse; +import jakarta.transaction.Transactional; +import org.springframework.stereotype.Service; + +@Transactional +@Service +public interface CommentService { + + CreateCommentResponse createComment(CreateCommentRequest createCommentRequest); + +} 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..f91e3b1 --- /dev/null +++ b/src/main/java/com/cow/cow_mvc_practice/comment/service/CommentServiceImpl.java @@ -0,0 +1,44 @@ +package com.cow.cow_mvc_practice.comment.service; + +import com.cow.cow_mvc_practice.comment.dto.request.CreateCommentRequest; +import com.cow.cow_mvc_practice.comment.dto.response.CreateCommentResponse; +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; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@RequiredArgsConstructor +@Service +@Transactional +public class CommentServiceImpl implements CommentService{ + private final CommentJPARepository commentRepository; + private final MemberJPARepository memberRepository; + private final PostJPARepository postRepository; + + @Override + public CreateCommentResponse createComment(CreateCommentRequest createCommentRequest) { + Member member = findMember(createCommentRequest.getMemberId()); + Post post = findPost(createCommentRequest.getPostId()); + + Comment comment = Comment.of(createCommentRequest.getContent(), post, member); + commentRepository.save(comment); + post.addComment(comment); + return CreateCommentResponse.from(comment); + } + + private Post findPost(Long postId) { + return postRepository.findById(postId) + .orElseThrow(() -> new EntityNotFoundException("[Error] 게시글를 찾을 수 없습니다.")); + } + + private Member findMember(Long memberId) { + return memberRepository.findById(memberId) + .orElseThrow(() -> new EntityNotFoundException("[Error] 회원를 찾을 수 없습니다.")); + } +} 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..77472af 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,7 @@ package com.cow.cow_mvc_practice.member.controller; +import com.cow.cow_mvc_practice.member.dto.request.UpdateMemberRequest; +import com.cow.cow_mvc_practice.member.dto.response.CreateMemberResponse; import java.util.List; import org.springframework.web.bind.annotation.GetMapping; @@ -10,9 +12,7 @@ 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.entity.Member; +import com.cow.cow_mvc_practice.member.dto.request.CreateMemberRequest; import com.cow.cow_mvc_practice.member.service.MemberService; import lombok.RequiredArgsConstructor; @@ -24,39 +24,29 @@ 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 적용 */ @PostMapping("/new") - public MemberResponse create(@RequestBody final MemberRequest memberRequest) { - return memberService.join(memberRequest); + public CreateMemberResponse create(@RequestBody final CreateMemberRequest createMemberRequest) { + return memberService.join(createMemberRequest); } @GetMapping("/{memberId}") - public MemberResponse findMember(@PathVariable final Long memberId) { + public CreateMemberResponse findMember(@PathVariable final Long memberId) { return memberService.findOne(memberId); } @GetMapping() - public MemberResponse findMemberQuery(@RequestParam final Long memberId) { + public CreateMemberResponse findMemberQuery(@RequestParam final Long memberId) { return memberService.findOne(memberId); } - @GetMapping("all") - public List findMembers() { + @GetMapping("/all") + public List findMembers() { return memberService.findAll(); } + + @PostMapping("/{memberId}") + public CreateMemberResponse editMember(@PathVariable final Long memberId, final UpdateMemberRequest updateMemberRequest) { + return memberService.update(memberId, updateMemberRequest); + } } 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 deleted file mode 100644 index c0dcd9c..0000000 --- a/src/main/java/com/cow/cow_mvc_practice/member/controller/dto/request/MemberRequest.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.cow.cow_mvc_practice.member.controller.dto.request; - -import com.cow.cow_mvc_practice.member.entity.Member; - -import lombok.Getter; - -@Getter -public class MemberRequest { - String name; - - public Member toEntity() { - return Member.builder() - .name(name) - .build(); - } -} 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 deleted file mode 100644 index 94429b9..0000000 --- a/src/main/java/com/cow/cow_mvc_practice/member/controller/dto/request/UpdateMemberRequest.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.cow.cow_mvc_practice.member.controller.dto.request; - -import lombok.Getter; - -@Getter -public class UpdateMemberRequest { - - private String name; -} diff --git a/src/main/java/com/cow/cow_mvc_practice/member/dto/request/CreateMemberRequest.java b/src/main/java/com/cow/cow_mvc_practice/member/dto/request/CreateMemberRequest.java new file mode 100644 index 0000000..48f3890 --- /dev/null +++ b/src/main/java/com/cow/cow_mvc_practice/member/dto/request/CreateMemberRequest.java @@ -0,0 +1,15 @@ +package com.cow.cow_mvc_practice.member.dto.request; + +import com.cow.cow_mvc_practice.member.entity.Member; +import lombok.Getter; + +@Getter +public class CreateMemberRequest { + private String name; + + public static Member toEntity(String name) { + return Member.builder() + .name(name) + .build(); + } +} diff --git a/src/main/java/com/cow/cow_mvc_practice/member/dto/request/UpdateMemberRequest.java b/src/main/java/com/cow/cow_mvc_practice/member/dto/request/UpdateMemberRequest.java new file mode 100644 index 0000000..4674b27 --- /dev/null +++ b/src/main/java/com/cow/cow_mvc_practice/member/dto/request/UpdateMemberRequest.java @@ -0,0 +1,16 @@ +package com.cow.cow_mvc_practice.member.dto.request; + +import com.cow.cow_mvc_practice.member.entity.Member; +import lombok.Getter; + +@Getter +public class UpdateMemberRequest { + + private String name; + + public static Member toEntity(String name) { + return Member.builder() + .name(name) + .build(); + } +} 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/dto/response/CreateMemberResponse.java similarity index 51% rename from src/main/java/com/cow/cow_mvc_practice/member/controller/dto/response/MemberResponse.java rename to src/main/java/com/cow/cow_mvc_practice/member/dto/response/CreateMemberResponse.java index 9e3a77b..be9f40b 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/dto/response/CreateMemberResponse.java @@ -1,4 +1,4 @@ -package com.cow.cow_mvc_practice.member.controller.dto.response; +package com.cow.cow_mvc_practice.member.dto.response; import com.cow.cow_mvc_practice.member.entity.Member; @@ -6,20 +6,22 @@ import lombok.Getter; @Getter -public class MemberResponse { +public class CreateMemberResponse { private final Long id; private final String name; @Builder - private MemberResponse(final Long id, final String name) { + private CreateMemberResponse(final Long id, final String name) { this.id = id; this.name = name; } - public static MemberResponse from(final Member member) { - return MemberResponse.builder() + public static CreateMemberResponse from(final Member member) { + return CreateMemberResponse.builder() .id(member.getId()) .name(member.getName()) .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 00d2b1c..886e058 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,6 +1,8 @@ package com.cow.cow_mvc_practice.member.entity; +import com.cow.cow_mvc_practice.comment.entity.Comment; import java.util.ArrayList; +import java.util.Collection; import java.util.List; import com.cow.cow_mvc_practice.post.entity.Post; @@ -50,4 +52,12 @@ public static Member of(Long id, String name) { .name(name) .build(); } + + public void updateName(String name) { + this.name = name; + } + + @OneToMany(mappedBy = "member") + private Collection comment; + } 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 dcfaceb..0000000 --- a/src/main/java/com/cow/cow_mvc_practice/member/repository/MemberRepositoryImpl.java +++ /dev/null @@ -1,34 +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 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/MemberService.java b/src/main/java/com/cow/cow_mvc_practice/member/service/MemberService.java index 06cc296..7ccfb3f 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,22 +1,21 @@ package com.cow.cow_mvc_practice.member.service; -import java.util.ArrayList; +import com.cow.cow_mvc_practice.member.dto.request.CreateMemberRequest; +import com.cow.cow_mvc_practice.member.dto.request.UpdateMemberRequest; +import com.cow.cow_mvc_practice.member.dto.response.CreateMemberResponse; 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 { /* 기본 */ - // void join(MemberRequest memberRequest); + // void join(CreateMemberRequest memberRequest); // Member findOne(Long memberId); - /* MemberResponse dto 적용 */ - MemberResponse findOne(Long memberId); - MemberResponse join(MemberRequest memberRequest); - List findAll(); + /* CreateMemberResponse dto 적용 */ + CreateMemberResponse findOne(Long memberId); + CreateMemberResponse join(CreateMemberRequest memberRequest); + List findAll(); + CreateMemberResponse update(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 edcd37b..88d24fd 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,16 +1,14 @@ package com.cow.cow_mvc_practice.member.service; +import com.cow.cow_mvc_practice.member.dto.request.UpdateMemberRequest; +import com.cow.cow_mvc_practice.member.dto.response.CreateMemberResponse; 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.member.controller.dto.request.MemberRequest; -import com.cow.cow_mvc_practice.member.controller.dto.response.MemberResponse; +import com.cow.cow_mvc_practice.member.dto.request.CreateMemberRequest; 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; @@ -20,43 +18,39 @@ 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()); + public CreateMemberResponse join(CreateMemberRequest createMemberRequest) { + Member member = Member.from(createMemberRequest.getName()); memberRepository.save(member); - return MemberResponse.from(member); + return CreateMemberResponse.from(member); } - @Transactional(readOnly = true) - @Override - public MemberResponse findOne(Long memberId) { - Member member = memberRepository.findById(memberId) - .orElseThrow(() -> new EntityNotFoundException("[Error] 사용자를 찾을 수 없습니다.")); - return MemberResponse.from(member); - } @Override - public List findAll() { + public List findAll() { List members = memberRepository.findAll(); return members.stream() - .map(MemberResponse::from) + .map(CreateMemberResponse::from) .collect(Collectors.toList()); } -} \ No newline at end of file + + @Transactional(readOnly = true) + @Override + public CreateMemberResponse findOne(Long memberId) { + Member member = findMember(memberId); + return CreateMemberResponse.from(member); + } + + @Override + public CreateMemberResponse update(Long memberId, UpdateMemberRequest updateMemberRequest) { + Member member = findMember(memberId); + member.updateName(updateMemberRequest.getName()); + return CreateMemberResponse.from(member); + } + + private Member findMember(Long memberId) { + return memberRepository.findById(memberId) + .orElseThrow(() -> new EntityNotFoundException("[Error] 사용자를 찾을 수 없습니다.")); + } +} 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..c0a4462 --- /dev/null +++ b/src/main/java/com/cow/cow_mvc_practice/post/controller/PostController.java @@ -0,0 +1,48 @@ +package com.cow.cow_mvc_practice.post.controller; + +import com.cow.cow_mvc_practice.post.dto.request.CreatePostRequest; +import com.cow.cow_mvc_practice.post.dto.response.CreatePostResponse; +import com.cow.cow_mvc_practice.post.service.PostService; +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +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; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/posts") +@RequiredArgsConstructor +public class PostController { + + private final PostService postService; + + // 게시글 생성 + @PostMapping("/new") + public CreatePostResponse createPost(@RequestBody final CreatePostRequest createPostRequest) { + return postService.createPost(createPostRequest); + } + + // 특정 게시글 조회 + @GetMapping("/{postId}") + public CreatePostResponse findPost(@PathVariable Long postId) { + return postService.findOnePost(postId); + } + + // 모든 게시글 조회 + @GetMapping("/all") + public List findAllPost() { + return postService.findAllPost(); + } + + // 게시글 삭제 + @DeleteMapping("/{postId}") + public ResponseEntity deletePost(@PathVariable Long postId) { + postService.delete(postId); + return ResponseEntity.ok(postId); + } +} diff --git a/src/main/java/com/cow/cow_mvc_practice/post/dto/request/CreatePostRequest.java b/src/main/java/com/cow/cow_mvc_practice/post/dto/request/CreatePostRequest.java new file mode 100644 index 0000000..9e5371c --- /dev/null +++ b/src/main/java/com/cow/cow_mvc_practice/post/dto/request/CreatePostRequest.java @@ -0,0 +1,18 @@ +package com.cow.cow_mvc_practice.post.dto.request; + +import com.cow.cow_mvc_practice.post.entity.Post; +import lombok.Getter; + +@Getter +public class CreatePostRequest { + private Long memberId; + private String title; + private String content; + + public static Post toEntity(String title, String content) { + return Post.builder() + .title(title) + .content(content) + .build(); + } +} diff --git a/src/main/java/com/cow/cow_mvc_practice/post/dto/response/CreatePostResponse.java b/src/main/java/com/cow/cow_mvc_practice/post/dto/response/CreatePostResponse.java new file mode 100644 index 0000000..df5d39e --- /dev/null +++ b/src/main/java/com/cow/cow_mvc_practice/post/dto/response/CreatePostResponse.java @@ -0,0 +1,33 @@ +package com.cow.cow_mvc_practice.post.dto.response; + +import com.cow.cow_mvc_practice.post.entity.Post; +import lombok.Builder; +import lombok.Getter; + +@Getter +public class CreatePostResponse { + private final Long id; + private final String title; + private final String content; + private final String memberName; + private final int commentSize; + + @Builder + private CreatePostResponse(Long id, String title, String content, String memberName, int commentSize) { + this.id = id; + this.title = title; + this.content = content; + this.memberName = memberName; + this.commentSize = commentSize; + } + + public static CreatePostResponse from(final Post post) { + return CreatePostResponse.builder() + .id(post.getId()) + .title(post.getTitle()) + .content(post.getContent()) + .memberName(post.getMemberName()) + .commentSize(post.getComments().size()) + .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..737e372 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,10 @@ 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.cow.cow_mvc_practice.utils.BaseEntity; +import jakarta.persistence.CascadeType; import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.FetchType; @@ -10,15 +13,21 @@ 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; import lombok.NoArgsConstructor; +import org.springframework.data.annotation.CreatedDate; @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) // 생성자를 통해서 값 변경 목적으로 접근하는 메시지들 차단 @Entity -public class Post { +public class Post extends BaseEntity { + @Id @Column(name = "post_id") @GeneratedValue(strategy = GenerationType.IDENTITY) @@ -32,18 +41,34 @@ public class Post { @JoinColumn(name = "member_id") private Member member; + @OneToMany(mappedBy = "post", cascade = CascadeType.ALL) + private List comments = new ArrayList<>(); + + @Builder - private Post(final String title, final String content, final Member member) { + private Post( final Long id, final String title, final String content, final Member member, final List comments, final LocalDateTime createdAt) { + this.id = id; this.title = title; this.content = content; this.member = member; + this.comments = comments; + super.createdAt = createdAt; } - public static Post from(final String title, final String content, final Member member) { + public static Post of(String title, String content, Member member) { return Post.builder() - .title(title) - .content(content) - .member(member) - .build(); + .title(title) + .content(content) + .member(member) + .build(); + } + + public void addComment(Comment comment) { + this.comments.add(comment); + } + + + public String getMemberName() { + return this.member.getName(); } -} \ 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..2eafe69 --- /dev/null +++ b/src/main/java/com/cow/cow_mvc_practice/post/repository/PostJPARepository.java @@ -0,0 +1,8 @@ +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 { + +} 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..39b89df --- /dev/null +++ b/src/main/java/com/cow/cow_mvc_practice/post/service/PostService.java @@ -0,0 +1,16 @@ +package com.cow.cow_mvc_practice.post.service; + +import com.cow.cow_mvc_practice.post.dto.request.CreatePostRequest; +import com.cow.cow_mvc_practice.post.dto.response.CreatePostResponse; +import java.util.List; + +public interface PostService { + + CreatePostResponse createPost(CreatePostRequest postRequest); + + CreatePostResponse findOnePost(Long postId); + + List findAllPost(); + + void 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..d140db5 --- /dev/null +++ b/src/main/java/com/cow/cow_mvc_practice/post/service/PostServiceImpl.java @@ -0,0 +1,62 @@ +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.dto.request.CreatePostRequest; +import com.cow.cow_mvc_practice.post.dto.response.CreatePostResponse; +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.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 CreatePostResponse createPost(CreatePostRequest createPostRequest) { + Member member = findMember(createPostRequest.getMemberId()); + Post post = Post.of(createPostRequest.getTitle(), createPostRequest.getContent(), member); + postRepository.save(post); + return CreatePostResponse.from(post); + } + + @Transactional(readOnly = true) + @Override + public CreatePostResponse findOnePost(Long postId) { + Post post = findPost(postId); + return CreatePostResponse.from(post); + } + + @Override + public List findAllPost() { + List posts = postRepository.findAll(); + return posts.stream() + .map(CreatePostResponse::from) + .collect(Collectors.toList()); + } + + @Override + public void delete(Long postId) { + Post post = findPost(postId); + postRepository.delete(post); + } + + private Post findPost(Long postId) { + return postRepository.findById(postId) + .orElseThrow(() -> new EntityNotFoundException("[Error] 게시글를 찾을 수 없습니다.")); + } + + private Member findMember(Long memberId) { + return memberRepository.findById(memberId) + .orElseThrow(() -> new EntityNotFoundException("[Error] 회원를 찾을 수 없습니다.")); + } +} diff --git a/src/main/java/com/cow/cow_mvc_practice/utils/BaseEntity.java b/src/main/java/com/cow/cow_mvc_practice/utils/BaseEntity.java new file mode 100644 index 0000000..4b8edd4 --- /dev/null +++ b/src/main/java/com/cow/cow_mvc_practice/utils/BaseEntity.java @@ -0,0 +1,20 @@ +package com.cow.cow_mvc_practice.utils; + +import jakarta.persistence.Column; +import jakarta.persistence.EntityListeners; +import jakarta.persistence.MappedSuperclass; +import java.time.LocalDateTime; +import lombok.Getter; +import org.springframework.data.annotation.CreatedDate; +import org.springframework.data.jpa.domain.support.AuditingEntityListener; + +@EntityListeners(AuditingEntityListener.class) +@Getter +@MappedSuperclass +public abstract class BaseEntity { + + @CreatedDate + @Column(updatable = false) + protected LocalDateTime createdAt; + +} diff --git a/src/test/java/com/cow/cow_mvc_practice/NoArgsConstructorTest.java b/src/test/java/com/cow/cow_mvc_practice/NoArgsConstructorTest.java index ac5afe6..31be27e 100644 --- a/src/test/java/com/cow/cow_mvc_practice/NoArgsConstructorTest.java +++ b/src/test/java/com/cow/cow_mvc_practice/NoArgsConstructorTest.java @@ -24,11 +24,11 @@ public class NoArgsConstructorTest { @BeforeEach void makeEntity() { - Member member = Member.from("나바보"); + Member member = Member.from("경호는 진짜 바보"); em.persist(member); - Post post = Post.from("글 제목입니다.", "글 내용입니다.", member); + Post post = Post.of("글 제목입니다.", "글 내용입니다.", member); em.persist(post); }