0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

댓글

0
Posted at
  1. 概要 (개요)
    이번 포스팅에서는 기존에 완성한 게시판 기능 위에 댓글(Comment) 기능을 추가했습니다.
    이번 구현의 핵심은 하나의 게시글(Board)에 여러 개의 댓글(Comment)이 달릴 수 있는 일대다(1:N) 데이터베이스 관계를 JPA의 @ManyToOne 어노테이션을 활용해 객체지향적으로 매핑하고, 외래키(FK)를 제어하는 방법을 학습하는 것입니다.

  2. テーブル設計와 関連付け (테이블 설계와 연관 관계)
    데이터베이스 관점에서 BOARDS 테이블과 COMMENTS 테이블은 board_id라는 외래키를 통해 부모와 자식 관계로 연결됩니다. JPA에서는 이를 자바 객체 참조 방식으로 매핑합니다.

📝 댓글 엔티티 구현 (Comment.java)

@Entity
@Table(name = "COMMENTS")
@Getter
@NoArgsConstructor
public class Comment {

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

    private String content; // 댓글 내용
    private String writer;  // 댓글 작성자 (세션 닉네임)

    // 💡 핵심: 多対一(ManyToOne) 릴레이션 설정
    // 여러 댓글(Many)은 하나의 게시글(One)에 소속됩니다.
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "board_id") // DB 상에 board_id라는 외래키(FK) 컬럼 생성
    private Board board;

    @Builder
    public Comment(String content, String writer, Board board) {
        this.content = content;
        this.writer = writer;
        this.board = board;
    }
}
  1. Repository & Service 구현
    ① Repository 확장 (CommentRepository.java)
    특정 게시글에 달린 댓글들만 쏙 필터링해서 꺼내오기 위해 JPA의 쿼리 메서드 규칙(findByBoardId)을 정의했습니다.
public interface CommentRepository extends JpaRepository<Comment, Long> {
    // board_id를 기준으로 댓글 리스트를 조회하는 메서드 자동 생성
    List<Comment> findByBoardId(Long boardId);
}

② 비즈니스 로직 작성 (CommentService.java)
댓글을 등록할 때 원본 게시글 객체(Board)를 먼저 조회한 뒤, 댓글 엔티티를 빌더로 조립할 때 부모 객체로 매핑하여 저장합니다.

@Service
@RequiredArgsConstructor
public class CommentService {

    private final CommentRepository commentRepository;
    private final BoardRepository boardRepository;

    /**
     * 댓글 작성 처리 (부모 엔티티와 연동)
     */
    @Transactional
    public Long writeComment(Long boardId, String content, String writer) {
        Board board = boardRepository.findById(boardId)
                .orElseThrow(() -> new IllegalArgumentException("存在しない投稿です。ID: " + boardId));

        Comment comment = Comment.builder()
                .content(content)
                .writer(writer)
                .board(board) // 연관 관계 매핑!
                .build();

        return commentRepository.save(comment).getId();
    }
}
  1. ViewController 데이터 통합 렌더링
    사용자가 게시글 상세 페이지에 접근했을 때, 글 내용(board)뿐만 아니라 해당 글에 소속된 댓글 리스트(comments)까지 한 보따리에 담아서 화면(Thymeleaf)으로 전달하도록 수정했습니다.
@GetMapping("/board/detail")
public String detailPage(@RequestParam("id") Long id, Model model, HttpSession session) {
    // 1. 원본 게시글 데이터 조회
    Board board = boardService.findPostById(id);
    model.addAttribute("board", board);
    
    // 2. 해당 게시글의 자식 댓글 리스트 조회 (추가된 로직)
    List<Comment> comments = commentService.findCommentsByBoardId(id);
    model.addAttribute("comments", comments);
    
    model.addAttribute("session", session); 
    return "detail";
}
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?