64일차 (2) - 스프링 (댓글)

Yohan·2024년 5월 23일
0

코딩기록

목록 보기
96/156
post-custom-banner

댓글기능 설계

db설계 및 Reply(댓글) 클래스

  • board_no을 외래키로 가지고 있다.
package com.study.springstudy.springmvc.chap05.entity;

/*
-- 댓글 테이블 생성
CREATE TABLE tbl_reply (
	reply_no INT(8) PRIMARY KEY auto_increment,
    reply_text VARCHAR(1000) NOT NULL,
    reply_writer VARCHAR(100) NOT NULL,
    reply_date DATETIME default current_timestamp,
    board_no INT(8),
    constraint fk_reply
    foreign key (board_no)
    references tbl_board (board_no)
    on delete cascade
);
 */

import lombok.*;

import java.time.LocalDateTime;

@Getter @ToString
@EqualsAndHashCode
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class Reply {

    private long replyNo;
    @Setter
    private String replyText;
    private String replyWriter;
    private LocalDateTime replyDate;
    private long boardNo;

}

ReplyMapper

@Mapper
public interface ReplyMapper {

    // 댓글 등록
    boolean save(Reply reply);

    // 댓글 수정
    boolean modify(Reply reply);

    // 댓글 삭제
    boolean delete(long replyNo);

    // 특정 게시물에 달린 댓글 목록 조회 - 게시물 번호 파라미터 필요
    List<Reply> findAll(long boardNo);

    // 총 댓글 수 조회
    int count(long boardNo);
}

ReplyMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.study.springstudy.springmvc.chap05.ReplyMapper">

    <insert id="save">
        INSERT INTO tbl_reply
        (reply_text, reply_writer, board_no)
        VALUES
        (#{replyText}, #{replyWriter}, #{boardNo})
    </insert>

    <update id="modify">
        UPDATE tbl_reply
        SET reply_text = #{replyText}
        WHERE reply_no = #{replyNo}
    </update>

    <delete id="delete">
        DELETE FROM tbl_reply
        WHERE reply_no = #{replyNo}
    </delete>

    <select id="findAll" resultType="reply">
        SELECT * FROM tbl_reply
        WHERE board_no = #{boardNo}
        ORDER BY reply_no
    </select>

    <select id="count" resultType="int">
        SELECT COUNT(*)
        FROM tbl_reply
        WHERE board_no = #{boardNo}
    </select>

</mapper>

ReplyMapperTest

  • 댓글을 테스트하기 위해선 게시글도 필요하기 때문에 게시글도 같이 테스트

@Builder

  • 테스트 데이터를 추가할 때 Board b = new Board().. 의 방식으로 추가했었는데 @Builder 어노테이션을 통해 객체 생성을 할 수 있다.
    • Board, Reply 클래스에 @Builder를 입력하여 객체 생성가능
package com.study.springstudy.springmvc.chap05;

import com.study.springstudy.springmvc.chap04.entity.Board;
import com.study.springstudy.springmvc.chap04.mapper.BoardMapper;
import com.study.springstudy.springmvc.chap05.entity.Reply;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.List;

import static org.junit.jupiter.api.Assertions.*;

@SpringBootTest
class ReplyMapperTest {

    @Autowired BoardMapper boardMapper;
    @Autowired ReplyMapper replyMapper;

//    @Test
//    @DisplayName("")
//    void bulkInsert() {
//        // 게시물 100개와 댓글 5000개를 랜덤으로 등록
//        for (int i = 1; i <= 100; i++) {
//            Board b = Board.builder()
//                    .title("재밌는 글" + i)
//                    .content("응 개노잼이야~~" + i)
//                    .writer("아무무나" + i)
//                    .build();
//
//            boardMapper.save(b);
//        }
//
//        for (int i = 1; i <= 5000; i++) {
//            Reply reply = Reply.builder()
//                    .replyText("하하호호댓글" + i)
//                    .replyWriter("꾸러긔" + i)
//                    .boardNo((long) (Math.random() * 100 + 1))
//                    .build();
//
//            replyMapper.save(reply);
//        }
//    }

    @Test
    @DisplayName("전체조회")
    void findAllTest() {
        //given
        long boardNo = 1;
        //when
        List<Reply> replies = replyMapper.findAll(boardNo);
        //then
        replies.forEach(System.out::println);
    }

    @Test
    @DisplayName("댓글 삭제")
    void deleteTest() {
        //given
        long replyNo = 1;
        //when
        replyMapper.delete(replyNo);
        //then
    }
    
    @Test
    @DisplayName("댓글 수정")
    void modifyTest() {
        //given
        long replyNo = 2;
        Reply reply = Reply.builder()
                .replyNo(replyNo)
                .replyText("수정수정")
                .build();
        //when
        replyMapper.modify(reply);
        //then
    }
    
}

게시물과 댓글 연결

  • 게시물이 조회될 때 댓글도 같이 나타나게 하고싶고 그 게시물의 댓글 수도 나게 설계하여 수정하고싶다.

BoardMapper.xml의 findAll 쿼리문을 수정

<select id="findAll" resultType="com.study.springstudy.springmvc.chap04.dto.BoardFindAllDto">
        SELECT
            B.board_no,
            B.title,
            B.content,
            B.writer,
            B.reg_date_time,
            B.view_count,
            COUNT(R.reply_no) AS reply_count
        FROM tbl_board B
        LEFT OUTER JOIN tbl_reply R
        ON B.board_no = R.board_no
        <include refid="search" />
        GROUP BY B.board_no
        ORDER BY board_no DESC
        LIMIT #{pageStart}, #{amount}
    </select>

LEFT JOIN을 하는 이유

  • 게시물에는 댓글이 없을 수도 있다. LEFT JOIN을 해야 댓글이 없는 게시물도 나올 수 있다. INNER JOIN으로 진행하면 NULL값이 들어와 댓글이 없는 게시물은 나오지 않게된다.

Board 클래스에서는 COUNT(R.reply_no)를 받을 수 없다. 즉 Dto를 하나 생성해야한다.

BoardFindAllDto

package com.study.springstudy.springmvc.chap04.dto;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.ToString;

import java.time.LocalDateTime;

@Getter @ToString
@NoArgsConstructor
@AllArgsConstructor
public class BoardFindAllDto {

    private long boardNo;
    private String title;
    private String content;
    private String writer;
    private LocalDateTime regDateTime;
    private int viewCount;
    private int replyCount;

}

1. Service에서 Board -> BoardFindAllDto로 의존객체가 바뀐 것 수정

2. 또한 상세조회 할 때 댓글 목록을 같이 조회하게함

BoardService


  • 상세 조회할 때 댓글 목록을 모두 조회하기 위해 Dto로 댓글목록을 보낸다.

BoardDetailResponseDto

  • Dto에 댓글 리스트인 replies를 만들어 Service에서 setter를 통해 댓글목록을 보내주고 있다.

BoardListResponseDto

  • 사진처럼 리스트가 나올 때 화면에 게시물의 댓글 수가 보이게끔 하고싶어서 Dto에 댓글수 필드를 추가

검색 조건 option 태그 고정하기

  • 아래 사진처럼 12를 쓰고 검색버튼을 눌렀을 때 내가 선택했던 작성자에 그대로 머물게 할 수 있다.

선택된 게시물이 없을 때 문구 추가


profile
백엔드 개발자
post-custom-banner

0개의 댓글