Spring boot

2024.10.17 Blog 프로젝트 만들기(JPA) 댓글 쓰기 및 삭제 인터셉터 적용

정훈5 2024. 10. 17. 10:29

 

댓글 등록 화면 측 코드 수정

detail.mustache 부분 수정

<!-- 댓글 -->
    <div class="card mt-3">
        <!-- 댓글등록 -->
        <div class="card-body">
            <form action="/reply/save" method="post">
                <input type="hidden" name="boardId" value="{{boardId}}">
                <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>

 

ReplyDTO.java

package com.tenco.blog_v1.reply;

import com.tenco.blog_v1.board.Board;
import com.tenco.blog_v1.user.User;
import lombok.Getter;
import lombok.Setter;


public class ReplyDTO {

    @Getter
    @Setter
    public static class SaveDTO {
        private Integer boardId;
        private String comment;

        // DTO --> JPA 영속성 컨텍스트로 저장 한다.. 엔티티로 변환 해야 한다.
        public Reply toEntity(User sessionUser, Board board) {
            return Reply.builder()
                    .comment(comment)
                    .board(board)
                    .user(sessionUser)
                    .build();
        }

    }

}

 

 

ReplyJPARepository.java

package com.tenco.blog_v1.reply;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

import java.util.List;

// 어노테이션 생략 가능 -> IoC 처리 됨
public interface ReplyJPARepository extends JpaRepository<Reply, Integer> {

    // 기본적인 주요 메서드 제공 받음 (구현체를 만들어 준다.)
    
    // 1. 커스텀 쿼리를 만들어 본다. 어노테이션 사용
    // BoardId를 통해서 리플정보를 조회하는 기능
    @Query("select r from Reply r where r.board.id = :boardId")
    List<Reply> findByBoardId(@Param("boardId") Integer boardId); // 알아서 메서드의 바디를 만들어 준다.
    
}

 

 

 

 

 

 

ReplyService.java

package com.tenco.blog_v1.reply;

import com.tenco.blog_v1.board.Board;
import com.tenco.blog_v1.board.BoardRepository;
import com.tenco.blog_v1.common.errors.Exception403;
import com.tenco.blog_v1.common.errors.Exception404;
import com.tenco.blog_v1.user.User;
import jakarta.transaction.Transactional;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor
public class ReplyService {

    private final BoardRepository boardRepository;
    private final ReplyJPARepository replyJPARepository;

    // 댓글 쓰기
    @Transactional
    public void saveReply(ReplyDTO.SaveDTO reDto, User sessionUser) {
        // 댓글 작성시 게시글 존재 여부 반드시 확인
        Board board =  boardRepository
                .findById(reDto.getBoardId()).orElseThrow(() -> new Exception404("없는 게시글에 댓글을 작성 못해요"));

        Reply reply = reDto.toEntity(sessionUser, board);
        replyJPARepository.save(reply);
    }

    // 댓글 삭제
    @Transactional
    public void deleteReply(Integer replyId, Integer sessionUserId, Integer boardId) {
        // 댓글 존재 여부 확인
        Reply reply = replyJPARepository
                .findById(replyId).orElseThrow(() -> new Exception404("없는 댓글을 삭제 못해요"));
        // 권한 처리 확인
        if(!reply.getUser().getId().equals(sessionUserId)) {
            throw new Exception403("댓글 삭제 권한이 없어요");
        }

        if (!reply.getBoard().getId().equals(boardId)) {
            throw new Exception403("해당 게시글의 댓글이 아닙니다");
        }
        replyJPARepository.deleteById(replyId);
    }
}

 

 

 

ReplyController.java

package com.tenco.blog_v1.reply;

import com.tenco.blog_v1.user.User;
import jakarta.servlet.http.HttpSession;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;

@RequiredArgsConstructor
@Controller
public class ReplyController {

    private final ReplyService replyService;
    private final HttpSession session;

    // 댓글 생성 기능 만들기

    @PostMapping("/reply/save")
    public String save(ReplyDTO.SaveDTO reqDTO) {
        // 로그인 여부 확인
        User sessionUser = (User)session.getAttribute("sessionUser");
        if(sessionUser == null) {
            return "redirect:/login-form";
        }
        replyService.saveReply(reqDTO, sessionUser);
        return "redirect:/board/" + reqDTO.getBoardId();
    }

}

 

 

 

ReplyController.java 

댓글 삭제 추가

 // 댓글 삭제
    //@DeleteMapping("")
    @PostMapping("/board/{boardId}/reply/{replyId}/delete")
    public String delete(@PathVariable(name = "boardId")Integer boardId, @PathVariable(name = "replyId") Integer replyId) {
        // 삭제도 권한 확인
        User sessionUser = (User)session.getAttribute("sessionUser");
        if(sessionUser == null) {
            return "redirect:/login-form";
        }
        replyService.deleteReply(replyId, sessionUser.getId(), boardId);
        return "redirect:/board/" + boardId;
    }

 

 

detail.mustache

수정

 {{#replyOwner}}
                        <form action="/baord/{{board.id}}/reply/{{id}}/delete" method="post">
                            <button class="btn">🗑</button>
                        </form>
                    {{/replyOwner}}