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