-
[5주차] 댓글 CRUD 구현SpringBoot 2023. 12. 4. 01:32
* Board - Comment 간의 외래키 설정이 안 된다
-> DB 다 drop하고도 안 되는지 확인해 봐야, 일단 OnetoMany 어노테이션 적용이 안 된다
Comment.java
package gdsctuk.sbbasic.sptingbootstudybasic.entity; import jakarta.persistence.*; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; import org.springframework.data.annotation.CreatedDate; import org.springframework.data.annotation.LastModifiedDate; import org.springframework.data.jpa.domain.support.AuditingEntityListener; import java.time.LocalDateTime; @Getter @Setter @NoArgsConstructor @Entity @EntityListeners(AuditingEntityListener.class) @Table(name = "Comment") public class Comment { @Id @GeneratedValue(strategy= GenerationType.AUTO) @Column(nullable = false, updatable = false) private Long commentId; // @ManyToOne(fetch = FetchType.LAZY) // @JoinColumn(name = "boardId") @Column(updatable = false) //nullable = false, private Long bId; @Column(length = 20, nullable = false) private String commentWriter; @Column(length = 10000, nullable = false) private String commentContent; @CreatedDate private LocalDateTime commentWriteTime; @LastModifiedDate private LocalDateTime commentEditTime; private Boolean isDeleted; // Null default - soft delete 판별용 @Builder public Comment(Long commentId, Long bId, String commentWriter, String commentContent, LocalDateTime commentWriteTime, LocalDateTime commentEditTime) { this.commentId = commentId; this.bId = bId; this.commentWriter = commentWriter; this.commentContent = commentContent; this.commentWriteTime = commentWriteTime; this.commentEditTime = commentEditTime; } public void updateComment(String commentContent) { this.commentContent = commentContent; } public void delete() { this.isDeleted = true; } }
Response Dto(4개)
@Builder @NoArgsConstructor @AllArgsConstructor @Data public class CommentResponseBIdDto { private Long id; // Board id 값을 반환 (Data to Obj) } //---------------// package gdsctuk.sbbasic.sptingbootstudybasic.dto.response; import gdsctuk.sbbasic.sptingbootstudybasic.entity.Comment; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; import java.time.LocalDateTime; @Builder @NoArgsConstructor @AllArgsConstructor @Data public class CommentResponseDto { private Long commentId; private Long bId; private String commentWriter; private String commentContent; private LocalDateTime commentWriteTime; private LocalDateTime commentEditTime; public CommentResponseDto(Comment comment) { this.commentId = comment.getCommentId(); this.bId = comment.getBId(); this.commentWriter = comment.getCommentWriter(); this.commentContent = comment.getCommentContent(); this.commentWriteTime = comment.getCommentWriteTime(); this.commentEditTime = comment.getCommentEditTime(); } } //----------------// package gdsctuk.sbbasic.sptingbootstudybasic.dto.response; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; @Builder @NoArgsConstructor @AllArgsConstructor @Data public class CommentResponseIdDto { private Long id; // id 값을 반환 (Data to Obj) } //--------------------------/// package gdsctuk.sbbasic.sptingbootstudybasic.dto.response; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; import java.util.List; @Builder @NoArgsConstructor @AllArgsConstructor @Data public class CommentResponseListDto { private List<CommentResponseDto> commentList; //CommentResponseDto를 list 형태로 반환할 때 쓰이는 dto }
RequestDto(2개)
package gdsctuk.sbbasic.sptingbootstudybasic.dto.request; import lombok.*; @Builder @Getter @NoArgsConstructor @AllArgsConstructor @Data public class CommentRequestDto { private Long bId; private Long commentId; private String commentContent; private String commentWriter; } //-----------// package gdsctuk.sbbasic.sptingbootstudybasic.dto.request; import lombok.*; @Builder @Getter @NoArgsConstructor @AllArgsConstructor @Data public class CommentUpdateDto { private Long bId; private Long commentId; private String commentContent; private String commentWriter; }
CommentRepository.java
package gdsctuk.sbbasic.sptingbootstudybasic.repository; import gdsctuk.sbbasic.sptingbootstudybasic.entity.Comment; import org.springframework.data.jpa.repository.JpaRepository; import java.util.List; import java.util.Optional; public interface CommentRepository extends JpaRepository<Comment, Long> { //@Query("SELECT c FROM Comment c WHERE c.bId = :bId") //List<Comment> findAllByBId(Long id); // Long bId Comment save(Comment comment); Optional<Comment> findById(Long id); List<Comment> findAll(); }
findAllByBId로 bid가 같은 것들을 한번에 조회할 생각이었는데 이 부분이 잘 되지 않아 제외하고 진행하였다
그런데 이후 postman 테스트에서 역시 update와 list(by BoardId)가 제대로 작동하지 않는 문제 발생 ^~^...
CommentMapper.java
package gdsctuk.sbbasic.sptingbootstudybasic.mapper; import gdsctuk.sbbasic.sptingbootstudybasic.dto.request.CommentRequestDto; import gdsctuk.sbbasic.sptingbootstudybasic.dto.response.CommentResponseBIdDto; import gdsctuk.sbbasic.sptingbootstudybasic.dto.response.CommentResponseDto; import gdsctuk.sbbasic.sptingbootstudybasic.dto.response.CommentResponseIdDto; import gdsctuk.sbbasic.sptingbootstudybasic.dto.response.CommentResponseListDto; import gdsctuk.sbbasic.sptingbootstudybasic.entity.Comment; import org.springframework.stereotype.Component; import java.util.List; import java.util.stream.Collectors; @Component public class CommentMapper { public Comment toEntity(CommentRequestDto request) { // entity에 알맞게 mapping해주기 위해 선언 - 보드라는 엔티티에 매핑해 주기 위해 return Comment.builder() .bId(request.getBId()) .commentContent(request.getCommentContent()) .commentWriter(request.getCommentWriter()) // nullable = false 값들은 모두 포함 .build(); } public CommentResponseIdDto toResponseId(Comment comment){ return CommentResponseIdDto.builder() .id(comment.getCommentId()) .build(); } public CommentResponseBIdDto toResponseBId(Comment comment){ return CommentResponseBIdDto.builder() .id(comment.getBId()) .build(); } public CommentResponseDto toResponse(Comment comment) { return CommentResponseDto.builder() .commentId(comment.getCommentId()) .bId(comment.getBId()) .commentContent(comment.getCommentContent()) .commentEditTime(comment.getCommentEditTime()) .build(); } public CommentResponseListDto toListResponse(List<Comment> commentList) { List<CommentResponseDto> commentResponseList = commentList.stream().map(this::toResponse).collect(Collectors.toList()); // 순차 method/클래스 내의 toResponse 사용 return CommentResponseListDto.builder() .commentList(commentResponseList) .build(); } }
CommentService.java
package gdsctuk.sbbasic.sptingbootstudybasic.service; import gdsctuk.sbbasic.sptingbootstudybasic.dto.request.CommentRequestDto; import gdsctuk.sbbasic.sptingbootstudybasic.dto.request.CommentUpdateDto; import gdsctuk.sbbasic.sptingbootstudybasic.dto.response.CommentResponseDto; import gdsctuk.sbbasic.sptingbootstudybasic.dto.response.CommentResponseIdDto; import gdsctuk.sbbasic.sptingbootstudybasic.dto.response.CommentResponseListDto; import gdsctuk.sbbasic.sptingbootstudybasic.entity.Comment; import gdsctuk.sbbasic.sptingbootstudybasic.mapper.CommentMapper; import gdsctuk.sbbasic.sptingbootstudybasic.repository.CommentRepository; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.List; @Service @RequiredArgsConstructor public class CommentService { private final CommentRepository commentRepository; private final CommentMapper commentMapper; // 댓글 생성 public CommentResponseIdDto createComment(CommentRequestDto request) { Comment comment = commentRepository.save(commentMapper.toEntity(request)); // 값 저장 CommentResponseIdDto commentResponseIdDto = commentMapper.toResponseId(comment); //return commentMapper.toResponseId(board); return commentResponseIdDto; } // 댓글 List 조회 public CommentResponseListDto findAll(Long id) { List<Comment> comments = commentRepository.findAll(); // List는 s 붙여서 처리 많음 return commentMapper.toListResponse(comments); } // 댓글 하나 조회 public CommentResponseDto findOneComment(Long id) { Comment comment = commentRepository.findById(id) .orElseThrow(IllegalStateException::new); return commentMapper.toResponse(comment); } // 댓글 수정 @Transactional public CommentResponseDto updateComment(CommentUpdateDto request) { Comment comment = commentRepository.findById(request.getCommentId()) .orElseThrow(IllegalStateException::new); comment.updateComment(request.getCommentContent()); return commentMapper.toResponse(comment); } // 댓글 삭제 @Transactional public CommentResponseDto deleteComment(Long id) { Comment comment = commentRepository.findById(id) .orElseThrow(IllegalStateException::new); comment.delete(); return commentMapper.toResponse(comment); } }
CommentController.java
package gdsctuk.sbbasic.sptingbootstudybasic.controller; import gdsctuk.sbbasic.sptingbootstudybasic.dto.request.CommentRequestDto; import gdsctuk.sbbasic.sptingbootstudybasic.dto.request.CommentUpdateDto; import gdsctuk.sbbasic.sptingbootstudybasic.dto.response.CommentResponseDto; import gdsctuk.sbbasic.sptingbootstudybasic.dto.response.CommentResponseIdDto; import gdsctuk.sbbasic.sptingbootstudybasic.dto.response.CommentResponseListDto; import gdsctuk.sbbasic.sptingbootstudybasic.mapper.CommentMapper; import gdsctuk.sbbasic.sptingbootstudybasic.service.CommentService; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; @RequiredArgsConstructor @RestController @RequestMapping("/comments") public class CommentController { private final CommentService commentService; private final CommentMapper commentMapper; @PostMapping(value = "/create") public ResponseEntity<CommentResponseIdDto> createComment(@RequestBody CommentRequestDto request){ return ResponseEntity.ok(commentService.createComment(request)); } @GetMapping("/list/{id}") public ResponseEntity<CommentResponseListDto> findAll(@PathVariable @RequestBody Long id) { return ResponseEntity.ok(commentService.findAll(id)); } @GetMapping("/find/{id}") public ResponseEntity<CommentResponseDto> findById(@PathVariable Long id) { return ResponseEntity.ok(commentService.findOneComment(id)); } @PutMapping("/update/{id}") public ResponseEntity<CommentResponseDto> updateComment(@RequestBody CommentUpdateDto request) { return ResponseEntity.ok(commentService.updateComment(request)); } @DeleteMapping("/delete/{id}") public ResponseEntity<CommentResponseDto> deleteComment(@PathVariable Long id) { return ResponseEntity.ok(commentService.deleteComment(id)); } }
POSTMAN으로 CRUD test
Create
FindOne
아예 http 형식을 comments/board id/comment id 이런 식으로 구성해서
list 구성과 findOne을 수정해 봐야 할 것 같다
애초에 기본키를 comment_id와 board_id 두개 함께 사용해도 괜찮았을듯
Delete - soft delete
개선 사항(내 개인적으로)
1. 외래키 속성 살리기
2. board_id, comment_id를 함께 참조해서 find, update 기능 작동
두 가지가 필요해 보인다
일단 여기까지 해서 commit & push 해두기
'SpringBoot' 카테고리의 다른 글
ch4 - 방명록 프로젝트 톺아보기 (0) 2023.12.28 ch2 - Spring Data JPA (0) 2023.12.21 [4주차] 지난 피드백 반영, Git에 코드 올리기 (0) 2023.11.30 [3주차] CRUD(by JPA) 설계 후 Postman으로 실행하기 (1) 2023.11.28 [2주차]DB 설계(by JPA) (1) 2023.11.12