Reply Entity
package shop.mtcoding.blog.reply; import jakarta.persistence.*; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; import org.hibernate.annotations.CreationTimestamp; import shop.mtcoding.blog.board.Board; import shop.mtcoding.blog.user.User; import java.time.LocalDateTime; @NoArgsConstructor // 빈생성자가 필요 @Entity @Data @Table(name = "reply_tb") public class Reply { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private int id ; private String comment; //user_id 로 테이블 만들어짐. @ManyToOne(fetch = FetchType.LAZY) private User user ; @ManyToOne(fetch = FetchType.LAZY) private Board board ; @CreationTimestamp private LocalDateTime createdAt; @Transient private boolean isReplyOwner; @Builder public Reply(int id, String comment, User user, Board board, LocalDateTime createdAt) { this.id = id; this.comment = comment; this.user = user; this.board = board; this.createdAt = createdAt; } }
1. View 확인
댓글 작성은 댓글 내용만 받으면 된다. 하지만 작성시 게시글의 번호도 함께 받아야 하기 때문에 input 태그에서 hidden 으로 id 값을 같이 받는다.
<!-- 댓글등록 --> <div class="card-body"> <form action="/reply/save" method="post"> <input type="hidden" name="boardId" value="{{board.id}}"> // hidden 으로 게시글 id를 받음 <textarea class="form-control" rows="2" name="comment"></textarea> <div class="d-flex justify-content-end"> <button type="submit" class="btn btn-outline-primary mt-1">댓글등록</button> </div> </form> </div>
2. DTO 만들기
package shop.mtcoding.blog.reply; import lombok.Data; import shop.mtcoding.blog.board.Board; import shop.mtcoding.blog.user.User; public class ReplyRequest { @Data public static class SaveDTO{ private Integer boardId ; private String comment ; public Reply toEntity(User sessionUser, Board board) { return Reply.builder() .comment(comment) .board(board) .user(sessionUser) .build(); } } }
영속성 컨텍스트로 INSERT 를 할 때는 엔티티 타입만 가능하기 때문에 DTO를 통해 받은 데이터도 엔티티로 만들어 INSERT 한다.
3. 레파지토리, 컨트롤러, 서비스
ReplyJPARepository
public interface ReplyJPARepository extends JpaRepository<Reply,Integer> {}
ReplyService
@RequiredArgsConstructor @Service public class ReplyService { private final ReplyJPARepository replyJPARepository ; private final BoardJPARepository boardJPARepository ; @Transactional public Reply 댓글쓰기(ReplyRequest.SaveDTO requestDTO, User sessionUser) { Board board = boardJPARepository.findById(requestDTO.getBoardId()) .orElseThrow(() -> new Exception404("없는 게시글에 댓글을 작성할 수 없습니다.")); Reply reply = requestDTO.toEntity(sessionUser,board); replyJPARepository.save(reply); return reply ; } }
boardJPARepository.findById 를 통해 게시글이 있는지 우선 조회한다. 여기서 조회된 board 데이터를 toEntity에 전달한다.
ReplyController
import jakarta.servlet.http.HttpSession; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import shop.mtcoding.blog.user.User; @RequiredArgsConstructor @Controller public class ReplyController { private final ReplyService replyService ; private final HttpSession session; @PostMapping("/reply/save") public String save(ReplyRequest.SaveDTO requestDTO){ User sessionUser = (User) session.getAttribute("sessionUser"); Reply reply = replyService.댓글쓰기(requestDTO,sessionUser); return "redirect:/board/"+reply.getBoard().getId() ; } }
DB와 화면에 정상적으로 INSERT 되었다.
Share article