토이 프로젝트/게시판 프로젝트

11. 게시판 프로젝트 - 댓글 작성

코딍코딍 2022. 8. 14. 13:10

게시글에 댓글을 작성할 수 있도록 구현하였다.

따로 댓글을 관리하기 위해 BoardComment를 만들었다.

BoardCommentMember N:1관계이고 BoardCommentBoardN:1관계이다.

연관관계

 

BoardComment 생성

@Entity
@Getter
public class BoardComment {
    @Id
    @GeneratedValue
    private Long id;

    private String comment;
    private LocalDateTime createdDate;
    private String createdBy;

    @ManyToOne(fetch=FetchType.LAZY)
    @JoinColumn(name="member_id")
    private Member member;

    @ManyToOne(fetch=FetchType.LAZY)
    @JoinColumn(name="board_id")
    private Board board;

    public BoardComment() {}

    @Builder
    public BoardComment(String comment, LocalDateTime createdDate, String createdBy, Member member, Board board) {
        this.comment = comment;
        this.createdDate = createdDate;
        this.createdBy = createdBy;
        this.member = member;
        this.board = board;
    }

}
  • 식별자, 댓글, 작성일자, 작성자, 연관관계를 가진다.


Board

@OneToMany(mappedBy = "board", fetch=FetchType.LAZY)
List<BoardComment> boardComments = new ArrayList<>();

 

  • 연관관계 설정

Member

@OneToMany(mappedBy = "member", fetch=FetchType.LAZY)
private List<BoardComment> boardComments = new ArrayList<>();
  • 연관관계 설정

BoardCommentDto 생성

@Data
public class BoardCommentDto {

    private String comment;
    private LocalDateTime createdDate;
    private String createdBy;
    private Member member;
    private Board board;

    public BoardComment toEntity() {
        return BoardComment.builder()
                .comment(comment)
                .createdDate(createdDate)
                .createdBy(createdBy)
                .member(member)
                .board(board)
                .build();
    }
}
  • 컨트롤러와 뷰에 BoardComment를 보내지 않고 BoardCommentDto를 보내 데이터 교환

 

BoardRepository 생성

public interface BoardCommentRepository extends JpaRepository<BoardComment, Long> {
	 List<BoardComment> findByBoardId(Long boardId);
}
  • 새로운 조회기능을 추가하였다. - findByBoardId(Long boardId)
    • DB에 있는 BoardComment 엔티티의 board_id가 boardId와 같은 엔티티들을 List형태로 반환한다.


BoardCommentService 생성

@Service
@RequiredArgsConstructor
@Transactional
public class BoardCommentService {
    private final BoardCommentRepository boardCommentRepository;

    public void save(BoardComment boardComment) {
        boardCommentRepository.save(boardComment);
    }

    @Transactional(readOnly = true)
    public List<BoardComment> findAll(Long BoardId) {
        return boardCommentRepository.findByBoardId(BoardId);
    }
}
  • 댓글 추가 - save()
  • 해당 게시글의 댓글 반환 - findByBoardId(BoardId) 


BoardController - content() 수정, addComment() 생성

@GetMapping("/boardContent/{boardId}")
public String content(@PathVariable Long boardId, Model model,
 	   @SessionAttribute(name = SessionConst.LOGIN_MEMBER, required = false) MemberDto memberDto) {
    Board board = boardService.countVisitIncrease(boardId);
    String mine = boardService.myContent(memberDto.getId(), board.getMember().getId());
    BoardDto boardDto = new BoardDto(board);

    List<BoardComment> boardComments = boardCommentService.findAll(boardId);
    model.addAttribute("boardComments", boardComments);

    model.addAttribute("boardDto", boardDto);
    model.addAttribute("mine", mine);
    return "board/boardContent";
}

@PostMapping("/comment/{boardId}")
public String addcomment(@PathVariable Long boardId, @ModelAttribute BoardCommentDto boardCommentDto,
	@SessionAttribute(name=SessionConst.LOGIN_MEMBER, required = false) MemberDto memberDto, RedirectAttributes redirectAttributes) {

    boardCommentDto.setCreatedDate(LocalDateTime.now());
    boardCommentDto.setCreatedBy(memberDto.getLoginId());
    boardCommentDto.setBoard(boardService.findOne(boardId));
    boardCommentDto.setMember(memberService.findOne(memberDto.getId()));

    BoardComment boardComment = boardCommentDto.toEntity();
    boardCommentService.save(boardComment);

    redirectAttributes.addAttribute("boardId", boardId);
    return "redirect:/board/boardContent/{boardId}";
}
  • content()
    • 해당 게시글의 댓글을 모두 가져오는 코드를 추가했다.
    • boardCommentService의 findAll()에 boardId를 인자로 보내 해당 게시글의 댓글을 가져온다. 
  • addComment()
    • 뷰에서 받은 BoardCommentDto로 BoardComment를 만들어 DB에 저장한다.
    • 이후 뷰를 갱신하기 위해 게시글 뷰로 redirect한다.

 

boardContent.html 수정

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
<head>
    <title></title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0/umd/popper.min.js"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
    <link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.22/css/jquery.dataTables.css">
    <script type="text/javascript" charset="utf8" src="https://cdn.datatables.net/1.10.22/js/jquery.dataTables.js"></script>
    <link href="../../static/css/bootstrap.min.css" rel="stylesheet">
    <style>
        .fakeimg {
            height: 200px;
            background: #aaa;
        }
    </style>
    <link href="../../static/css/headers.css" rel="stylesheet">
</head>
<body>
<main>
    <header class="d-flex flex-wrap align-items-center justify-content-center justify-content-md-between py-3 mb-4 border-bottom">
        <a href="/" class="d-flex align-items-center col-md-3 mb-2 mb-md-0 text-dark text-decoration-none">
            <svg class="bi me-2" width="40" height="32" role="img" aria-label="Bootstrap"><use xlink:href="#bootstrap"></use></svg>
        </a>

        <ul class="nav col-12 col-md-auto mb-2 justify-content-center mb-md-0">
            <li><a href="/" class="nav-link px-2 link-secondary">Home</a></li>
            <li><a href="/board/boardList" class="nav-link px-2 link-dark">게시판</a></li>
            <li><a href="#" class="nav-link px-2 link-dark">About</a></li>
        </ul>

        <div class="col-md-3 text-end">
            <button type="button" class="btn btn-outline-primary me-2" onclick="location.href='/member/logout'">로그아웃</button>
        </div>
    </header>
</main>

<div class="container" style="margin-top:30px">
    <div class="row">
        <div class="col-sm-12">
            <div th:if="${mine.equals('true')}">
                <a th:href="@{'/board/edit/' + ${boardDto.id}}">
                    <button>수정</button>
                </a>
            </div>
            <div class="form-group">
                <h5 th:text="'제목 : ' + ${boardDto.title}"></h5>
            </div>
            <div>
                <td th:text="'작성자 : ' + ${boardDto.createdBy}"></td>
                <br><br>
            </div>
            <h5> 내용 </h5>
            <div style="border:1px solid; padding:10px;">
                <dl>
                    <dd th:text="${boardDto.content}"></dd>
                </dl>
            </div>
        </div>
    </div>
</div>
<!--여기부터-->
<form action="boardContent.html" th:action="@{'/board/comment/' + ${boardDto.id}}" method="post">
    <div class="comment-form" style="text-align: center;">
        <div class="comment-form2" style="width:300px;height: 200px;display: inline-block">
            <label for="comment">댓글 달기</label>
            <textarea class="form-control" id="comment" name="comment" rows="3"></textarea>
            <button type="submit" class="btn btn-primary" onclick="window.location.reload()">작성</button>
        </div>
    </div>
</form>
<div class="container">
    <table class="table table-hover">
        <tr>
            <th>번호</th>
            <th>작성자</th>
            <th>내용</th>
        </tr>
        </thead>
        <tbody>
        <tr th:each="boardComment : ${boardComments}">
            <td th:text="${boardComment.id}"></td>
            <td th:text="${boardComment.createdBy}"></td>
            <td th:text="${boardComment.comment}"></td>
        </tr>
        </tbody>
    </table>
</div>
<!--여기까지 추가-->
</body>
</html>

 

 

 

boardContent.html - 댓글작성 전

 

 

boardContent.html - 댓글작성 후