[User_공지사항] 댓글 등록, 목록, 수정 / 댓글 좋아요 싫어요 (3)

2024. 1. 25. 11:55Project/ShoppingMall

반응형

 

🟢 CommentEntity

 

▪️ noticeId 이용하여 NoticeEntity와 조인

@ManyToOne 다대일(Many-to-One) 관계

여러 댓글이 하나의 게시글에 속할 수 있음을 의미

 

@JoinColumn(name = "noticeId")

noticeId 컬럼이 댓글 테이블에서 외래 키로 사용

 

@ColumnDefault("0") : 해당하는 데이터베이스 컬럼의 기본값을 지정하는 데 사용

@Entity
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@ToString
@Builder
@Table(name = "comment")
@SequenceGenerator(name = "comment_SEQ",
                    sequenceName = "comment_SEQ",
                    initialValue = 1,
                    allocationSize = 1)
public class CommentEntity extends BaseEntity{

  @Id
  @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "comment_SEQ")
  private Integer commentId;

  @ManyToOne(fetch = FetchType.LAZY)
  @JoinColumn(name = "noticeId")
  private NoticeEntity noticeEntity;

  @Column(name = "commentWriter")
  private String commentWriter;

  @Column(name = "commentContent", nullable = false)
  private String commentContent;

  @ColumnDefault("0")
  @Column(name = "goodcnt")
  private  int goodcnt;               //좋아요

  @ColumnDefault("0")
  @Column(name = "badcnt")
  private  int badcnt;                //싫어요

}

 

▪️ 댓글 수정 처리

update 메서드를 통해 엔터티를 업데이트하고,

toDTO 메서드를 통해 엔터티를 DTO로 변환하여 필요한 경우 데이터 전송 객체로 사용

  //댓글을 업데이트할 때 사용
  //CommentDTO 객체를 매개변수로 받아와서 해당 객체에 저장된 댓글 내용을 사용해 엔터티의 댓글 내용을 업데이트
  public void update(CommentDTO updatedCommentDTO) {

    this.commentContent = updatedCommentDTO.getCommentContent();

  }

  //댓글 엔터티를 댓글 데이터 전송 객체(CommentDTO)로 변환
  //새로운 CommentDTO 객체를 생성
  //현재 엔터티의 commentId와 commentContent를 이 객체에 설정한 후 반환
  public CommentDTO toDTO() {

    CommentDTO commentDTO = new CommentDTO();

    commentDTO.setCommentId(this.commentId);
    commentDTO.setCommentContent(this.commentContent);

    return commentDTO;
  }

 

 

🟢 CommentDTO

@Getter
@Setter
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class CommentDTO {

  private Integer commentId;

  private Integer noticeId;

  private String commentWriter;

  private String commentContent;

  private  int goodcnt;

  private  int badcnt;

  private LocalDateTime reDate;

  private LocalDateTime modDate;

}

 

 

🟢 CommentRepository

▪️ ORDER BY c.commentId DESC :  "commentId" 필드를 기준으로 내림차순으로 정렬

@Repository
public interface CommentRepository extends JpaRepository<CommentEntity, Integer> {

  //부모레코드(공지사항 조회)
  //댓글 번호 기준 역순 정렬
  @Query("SELECT c FROM CommentEntity c WHERE c.noticeEntity.noticeId = :noticeId ORDER BY c.commentId DESC")
  List<CommentEntity> findByNoticeIdOrderByCommentIdDesc (Integer noticeId);
}

 

▪️ 댓글 좋아요 / 싫어요

  //댓글 좋아요
  @Modifying
  @Query("UPDATE CommentEntity c SET c.goodcnt = c.goodcnt+1 WHERE c.commentId = :commentId")
  void goodncnt (@Param("commentId") Integer commentId);

  //댓글 싫어요
  @Modifying
  @Query("UPDATE CommentEntity c SET c.badcnt = c.badcnt+1 WHERE c.commentId = :commentId")
  void badcnt (@Param("commentId") Integer commentId);

 

 

🟢 Comment Service

▪️ 댓글 등록 / 목록 / 댓글 좋아요&싫어요 / 삭제

@Service
@Transactional
@RequiredArgsConstructor
public class CommentService {

  private final NoticeRepository noticeRepository;
  private final CommentRepository commentRepository;
  private final ModelMapper modelMapper = new ModelMapper();


  //댓글 등록
  public CommentEntity insert (Integer noticeId, CommentDTO commentDTO) throws Exception {

    //부모 레코드 조회
    Optional<NoticeEntity> noticeEntity = noticeRepository.findById(noticeId);
    NoticeEntity result = noticeEntity.orElseThrow();

    //댓글등록
    CommentEntity commentEntity = modelMapper.map(commentDTO, CommentEntity.class);

    //부모레코드 정보 추가
    commentEntity.setNoticeEntity(result);

    //댓글저장
    commentRepository.save(commentEntity);

    return commentEntity;

  }


  // 댓글목록
  public List<CommentDTO> list(Integer noticeId) throws Exception {

    List<CommentEntity> commentEntityList = commentRepository.findByNoticeIdOrderByCommentIdDesc(noticeId);

    List<CommentDTO> commentDTOS = commentEntityList.stream()
        .map(commentEntity -> modelMapper.map(commentEntity, CommentDTO.class))
        .collect(Collectors.toList());

    return commentDTOS;

  }


  //댓글 좋아요
  public void goodcnt (Integer commentId) throws Exception {

    commentRepository.goodncnt(commentId);

  }

  //댓글 싫어요
  public void badcnt (Integer commentId) throws Exception {

    commentRepository.badcnt(commentId);

  }



  //댓글 삭제
  public void delete (Integer commentId) throws Exception {

    commentRepository.deleteById(commentId);

  }

}

 

▪️ 댓글 수정

  //댓글 수정
  public CommentDTO updateComment(Integer commentId, CommentDTO updatedCommentDTO) throws Exception {
    
    //댓글 조회
    CommentEntity targetComment = commentRepository.findById(commentId).orElseThrow();

    // 업데이트 작업 수행
    targetComment.update(updatedCommentDTO);

    // 댓글을 저장하고, 수정된 댓글의 DTO를 반환
    CommentEntity savedComment = commentRepository.save(targetComment);
    return savedComment.toDTO();

  }

 

 

🟢 Notice Service

▪️ 댓글이 있는 공지 사항 삭제

  //공지삭제 (댓글 삭제 후, 글 삭제)
  public void delete(Integer noticeId) throws Exception {

    commentRepository.deleteAll();

    noticeRepository.deleteById(noticeId);

  }

 

 

🟢 Notice Controller

▪️ 게시글 상세페이지 조회시, 댓글 불러오기

@Controller
@Transactional
@RequiredArgsConstructor
public class NoticeController {

  private final NoticeService noticeService;
  private final CommentService commentService;

  //공지상세
  @GetMapping("/notice_detail")
  public String usernoticedetail(Integer noticeId, Model model) throws Exception {

    //게시글 불러오기
    NoticeDTO noticeDTO = noticeService.findOne(noticeId);

    //댓글 불러오기
    List<CommentDTO> commentDTOS = commentService.list(noticeId);

    //이전, 다음 게시글 이동
    Integer prevNoticeId = noticeService.findPreviousNoticeId(noticeId);
    Integer nextNoticeId = noticeService.findNextNoticeId(noticeId);

    noticeService.noticeView(noticeId);

    model.addAttribute("noticeDTO", noticeDTO);
    model.addAttribute("commentDTOS", commentDTOS);

    model.addAttribute("prevNoticeId",prevNoticeId);
    model.addAttribute("nextNoticeId",nextNoticeId);

    return "/notice/notice_detail";

  }

}

 

 

 

🟢 CommentController

▪️ 댓글 등록 / 댓글 좋아요&싫어요 / 삭제

@Controller
@Transactional
@RequiredArgsConstructor
public class CommentController {

  private final CommentService commentService;


  //댓글 등록 처리
  @PostMapping("/commentinsert")
  public String commentInsert(Integer noticeId, CommentDTO commentDTO, RedirectAttributes redirectAttributes) throws Exception {

    commentService.insert(noticeId, commentDTO);

    redirectAttributes.addAttribute("noticeId", noticeId);

    return "redirect:/notice_detail";

  }


  // 수정 폼 조회
  @GetMapping("/commentupdate")
  public String commentupdateForm(@RequestParam("commentId") Integer commentId, CommentDTO updatedCommentDTO, Model model) throws Exception {

    CommentDTO commentDTO = commentService.updateComment(commentId, updatedCommentDTO);

    model.addAttribute("commentDTO", commentDTO);

    return "comment/comment_update_form";
  }

  // 수정 처리
  @PostMapping("/commentupdate")
  public String updateProc (Integer noticeId,
                            Integer commentId,
                            CommentDTO updatedCommentDTO,
                            RedirectAttributes redirectAttributes) throws Exception {
    
    commentService.updateComment(commentId, updatedCommentDTO);

    redirectAttributes.addAttribute("noticeId", noticeId);

    return "redirect:/notice_detail";

  }


  //댓글 좋아요
  @GetMapping("/commentgood")
  public String commentgood(Integer noticeId, Integer commentId, RedirectAttributes redirectAttributes) throws Exception {

    commentService.goodcnt(commentId);

    redirectAttributes.addAttribute("noticeId", noticeId);

    return "redirect:/notice_detail";

  }


  //댓글 싫어요
  @GetMapping("/commentbad")
  public String commentbad(Integer noticeId, Integer commentId, RedirectAttributes redirectAttributes) throws Exception {

    commentService.badcnt(commentId);

    redirectAttributes.addAttribute("noticeId", noticeId);

    return "redirect:/notice_detail";

  }


  //댓글 삭제
  @GetMapping("/commentdelete")
  public String commentdelete(Integer noticeId, Integer commentId, RedirectAttributes redirectAttributes) throws Exception {

    commentService.delete(commentId);

    redirectAttributes.addAttribute("noticeId", noticeId);

    return "redirect:/notice_detail";

  }

}

 

 


🟢 notice detail

▪️ 댓글 등록

댓글 등록 처리 post

                     <div class="row">
                        <div class="col-lg-12">
                            <div class="card mt-3 mb-3">
                                <div class="card-header">댓글</div>
                                <div class="card-body">
                                    <div class="card-body">
                                        <!-- 댓글 등록 폼 -->
                                        <form th:action="@{/commentinsert}" method="post">
                                            <input type="hidden" name="noticeId" th:value="${noticeDTO.noticeId}">
                                            <div class="mb-1 mt-1">
                                                <textarea class="form-control" rows="3" id="commentContent" name="commentContent"></textarea>
                                            </div>
                                            <input type="hidden" name="goodcnt" value="0">
                                            <input type="hidden" name="badcnt" value="0">
                                            <button type="submit" class="btn btn-primary admin-primary">댓글 등록</button>
                                        </form>
                                    </div>
                                </div>

 

▪️ 댓글 목록 + 수정

<div class="card-footer">
                                    <!-- 댓글 목록 -->
                                    <div class="card mt-2 mb-2" th:each="data:${commentDTOS}">
                                        <div class="card-header">
                                            작성일 : <span th:text="${#temporals.format(data.reDate, 'yyyy-MM-dd')}"></span><br>
                                            <a th:href="@{/commentgood(noticeId=${noticeDTO.noticeId}, commentId=${data.commentId})}">좋아요</a> : <span th:text="${data.goodcnt}"></span>
                                            <a th:href="@{/commentbad(noticeId=${noticeDTO.noticeId}, commentId=${data.commentId})}">싫어요</a> : <span th:text="${data.badcnt}"></span>
                                        </div>
                                        <div class="card-body">
                                            <!-- 댓글 내용 -->
                                            <span th:text="${data.commentContent}"></span>
                                        </div>
                                        <div class="card-footer">
                                            <!-- 수정 버튼 -->
                                            <button type="button" class="btn btn-primary admin-primary"
                                                    th:onclick="|toggleEditForm(${data.commentId})|">수정</button>
                                            <!-- 삭제 버튼 -->
                                            <button type="button" class="btn btn-primary admin-primary"
                                                    th:onclick="|location.href='@{/commentdelete(noticeId=${noticeDTO.noticeId}, commentId=${data.commentId})}'|">삭제</button>
                                        </div>
                                        <!-- 수정 모드 -->
                                        <form class="collapse multi-collapse" th:id="'editMode-' + ${data.commentId}"
                                              th:action="@{/commentupdate(noticeId=${noticeDTO.noticeId}, commentId=${data.commentId})}" method="post">
                                            <div class="form-group">
                                                <textarea class="form-control" id="commentContent" rows="3" th:text="${data.commentContent}" name="commentContent"></textarea>
                                            </div>
                                            <button type="submit" class="btn btn-primary admin-primary">수정 완료</button>
                                        </form>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>

                    <!-- 스크립트 추가 -->
                    <script th:inline="javascript">
                        function toggleEditForm(commentId) {
                            $('#editMode-' + commentId).collapse('toggle');
                        }
                    </script>

                </div>
            </div>
        </div>
    </div>
</div>
</body>
</html>

 

 

▪️ 댓글 수정 스크립트

수정 버튼을 누르면 toggleEditForm 활성화

th:inline → 해당 태그 내부의 코드를 어떤 형식으로 해석할지 지정

collapse   펼치기 상태

collapse('toggle')    엘리먼트가 숨겨져 있으면 펼치고, 펼쳐져 있으면 숨김

                    <script th:inline="javascript">
                        function toggleEditForm(commentId) {
                            $('#editMode-' + commentId).collapse('toggle');
                        }
                    </script>
반응형