Project/ShoppingMall
[User_공지사항] 댓글 등록, 목록, 수정 / 댓글 좋아요 싫어요 (3)
달해해
2024. 1. 25. 11:55
반응형
🟢 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>
반응형