쌓고 쌓다

[스프링 부트] 게시글 댓글 작성 - 9 본문

프로그래밍/spring

[스프링 부트] 게시글 댓글 작성 - 9

승민아 2023. 7. 10. 12:08

댓글(Comment) 테이블 생성

CREATE TABLE comment (
    id bigint NOT NULL auto_increment,
    pno bigint NOT NULL,
    writer VARCHAR(100) NOT NULL,
    content VARCHAR(300) NOT NULL,
    regdate DATETIME NOT NULL,
    PRIMARY KEY(id),
    FOREIGN KEY(pno) REFERENCES poster(id)
);

댓글이 포함되는 게시글의 PK를 외래키 pno로 가진다.

 

댓글(Comment) 클래스 생성

@Entity
public class Comment {

    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private Long pno;
    private String writer;

    private String content;

    @Column(name="regdate")
    private LocalDateTime regDate;
}

사용하지는 않았으나 @Table(name="reply")와 같이 매핑할 테이블 이름을 지정할 수 있다.

@GeneratedValue : 엔티티 기본 키 생성 전략으로 IDENTITY는 키본 키 생성을 DB에 위임하는 것이다.(AUTO_INCREMENT)

@Column : 필드명과 다른 테이블 컬럼과 매핑할때 필요하다.

 

+ regDate 컬럼을 regdate로 매핑 시켜주지 않으면 조회 SQL시 reg_date로 컬럼 조회가 이뤄져 컬럼 일치하지 않음.

 

CommentRepository

public interface SpringDataJpaCommentRepository extends JpaRepository<Comment, Long> {
    List<Comment> findByPno(Long pno);
}

SpringDataJpa에서 제공하는 findBy 방법으로 컬럼을 통해 조회할 수 있다.

나중에 게시글에 맞는 댓글들을 뽑아오기위해 댓글의 외래키 pno를 통해 찾도록 메소드를 작성했다.

 

CommentService

@Service
@Transactional
public class CommentService {

    private SpringDataJpaCommentRepository commentRepository;

    @Autowired
    public CommentService(SpringDataJpaCommentRepository commentRepository) {
        this.commentRepository = commentRepository;
    }

    public Long write(Comment comment) {
        comment.setRegDate(LocalDateTime.now());
        commentRepository.save(comment);
        return comment.getId();
    }

    public List<Comment> findComments(Long pno) {
        List<Comment> comments = commentRepository.findByPno(pno);
        return comments;
    }


}

게시글 작성때와 동일한 방식으로 작성했다.

추후에 Controller에서 해당 게시글에 포함된 댓글을 조회하기위한

findComments 메소드를 작성했다. 이 메소드는 commentRepository의 findByPno를 사용한다.

 

CommentController

@Controller
public class CommentController {

    private final CommentService commentService;
    @Autowired
    public CommentController(CommentService commentService) {
        this.commentService = commentService;
    }

    @PostMapping("/comment/write")
    public String commentWrite(Comment comment) {
        commentService.write(comment);
        return "redirect:/poster/read?id=" + comment.getPno();
    }

}

게시글 상세보기 페이지에서 form 태그를 통해 "/comment/write"로 POST 요청을 보낼 것이다.

이때 넘어오는 댓글을 CommentService를 통해 Repository에 넣는다.

그리고 해당 게시글 상세보기 페이지로 리다이렉션한다.

 

PosterController

@Controller
public class PosterController {

    private final PosterService posterService;
    private final CommentService commentService;

    @Autowired
    public PosterController(PosterService posterService, CommentService commentService) {
        this.posterService = posterService;
        this.commentService = commentService;
    }
    
    @GetMapping("/poster/read")
    public String read(Model model,@RequestParam(name = "id") Long id) {
        ...
        
        List<Comment> comments = commentService.findComments(id); // 추가 작성
        model.addAttribute("comments", comments); // 추가 작성
        return "posters/posterView";
    }

}

게시글 상세보기 요청시 해당 게시글의 댓글들을 조회하여 함께 넘겨주는 코드를 추가 작성한다.

이때 CommentService가 필요하므로 Poster,Comment 서비스를 같이 DI를 해준다.

 

 

posterView.html (게시글 상세보기)

(1) 댓글 작성

    <div>
        <form action="/comment/write" method="post">
            <div>
                <input type="text" name="writer"> <br>
                <input type="hidden" name="pno" th:value="${poster.id}">
                <textarea type="text" name="content"></textarea>
            </div>
            <div>
                <button type="submit">제출</button>
            </div>
        </form>
    </div>

댓글 작성시 해당 댓글이 포함되는 게시글의 고유 번호(PK)는 어떻게 전달하는가?

input 태그의 타입을 "hidden"으로하면 사용자에게 보이지 않는 입력 필드를 만들 수 있다.

이때 게시글의 PK를 댓글의 pno로 넣어 보내준다.

input의 hidden

 

hidden 방법말고 어떤 방법으로 게시글 PK를 넘길 수 있는지 ChatGPT에게 물어봤다.

 

(2) 댓글 조회

    <div>
        <ul th:each="comment : ${comments}">
            <li th:text="|${comment.writer} ${comment.content}|">
            </li>
        </ul>
    </div>

 

댓글 구현 결과

댓글 작성
DB 댓글

 

 

 

 

Comments