<Reply>
package tnut.blogback.model;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.CreationTimestamp;
import javax.persistence.*;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Entity
public class Reply { //댓글에 담길 내용: 닉네임(유저), 댓글 내용, 대댓글, 해당 게시글
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Lob
private String content;
@ManyToOne
@JsonIgnore
@JoinColumn(name = "parentReply_id")
private Reply parentReply;
@OneToMany(mappedBy = "parentReply", fetch = FetchType.LAZY, cascade = CascadeType.REMOVE)
@OrderBy("id asc ")
private List<Reply> subReplies = new ArrayList<>();
@ManyToOne //하나의 보드에 여러 댓글
@JsonIgnore //댓글에선 보드의 정보가 필요 없음
@JoinColumn(name = "board_id")
private Board board;
@CreationTimestamp
private Timestamp createDate;
}
<reply repository>
package tnut.blogback.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import tnut.blogback.model.Reply;
public interface ReplyRepository extends JpaRepository<Reply, Long> {
}
<reply service>
package tnut.blogback.service;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tnut.blogback.dto.ReplySaveRequestDto;
import tnut.blogback.dto.RereplySaveRequestDto;
import tnut.blogback.model.Board;
import tnut.blogback.model.Reply;
import tnut.blogback.repository.BoardRepository;
import tnut.blogback.repository.ReplyRepository;
@Service
public class ReplyService {
private final BoardRepository boardRepository;
private final ReplyRepository replyRepository;
public ReplyService(BoardRepository boardRepository, ReplyRepository replyRepository) {
this.boardRepository = boardRepository;
this.replyRepository = replyRepository;
}
@Transactional
public Reply replySave(ReplySaveRequestDto replySaveRequestDto) { //postMapping
Board board = boardRepository.findById(replySaveRequestDto.getBoard_id()) //보드 있는지 확인
.orElseThrow(() -> new IllegalArgumentException("이미 삭제된 게시글 입니다."));
Reply replyEntity = Reply.builder()
.board(board)
.content(replySaveRequestDto.getContent())
.build();
return replyRepository.save(replyEntity);
}
@Transactional
public Reply reReplySave(RereplySaveRequestDto reReplySaveRequestDto) { //대댓글
Reply parentReply = replyRepository.findById(reReplySaveRequestDto.getParentReply_id())
.orElseThrow(()->new IllegalArgumentException("이미 삭제된 댓글입니다."));
Reply replyEntity = Reply.builder()
.parentReply(parentReply)
.content(reReplySaveRequestDto.getContent())
.build();
return replyRepository.save(replyEntity);
}
@Transactional
public String replyDelete(Long id) { //댓글 삭제 DeleteMapping
replyRepository.deleteById(id);
return "success delete!";
}
}
<replySaveDto>
package tnut.blogback.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class ReplySaveRequestDto {
private Long board_id;
private String content;
}
<reReplySaveDto>
package tnut.blogback.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class RereplySaveRequestDto {
private Long parentReply_id;
private String content;
}
<reply controller>
package tnut.blogback.controller.api;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
import tnut.blogback.dto.ReplySaveRequestDto;
import tnut.blogback.dto.RereplySaveRequestDto;
import tnut.blogback.dto.ResponseDto;
import tnut.blogback.service.ReplyService;
@RequiredArgsConstructor
@RestController
public class ReplyApiController {
private ReplyService replyService;
@Autowired
public ReplyApiController(ReplyService replyService) {
this.replyService = replyService;
}
@PostMapping("/api/reply/save") //댓글 내용 받아서 저장
public ResponseDto<?> replySave (@RequestBody ReplySaveRequestDto replySaveRequestDto) {
return new ResponseDto<>(HttpStatus.OK.value(), replyService.replySave(replySaveRequestDto));
}
@PostMapping("/api/reReply/save") //댓글 내용 받아서 저장
public ResponseDto<?> reReplySave (@RequestBody RereplySaveRequestDto reReplySaveRequestDto) {
return new ResponseDto<>(HttpStatus.OK.value(), replyService.reReplySave(reReplySaveRequestDto));
}
@DeleteMapping("/api/reply/{id}/delete") //댓글 삭제
public ResponseDto<?> replyDelete (@PathVariable Long id) {
return new ResponseDto<>(HttpStatus.OK.value(), replyService.replyDelete(id));
}
}
<댓글을 단 게시글을 불러왔을 때 응답>
<Board 삭제 시>
아쉬운 점 : replySaveDto 하나로 대댓글도 구현할 수 있을거라 생각했는데 부족해서인지...안되는 건지...model에서 @ManyToOne은 optional이 가능하다고 되어 있으나 findById로 부모댓글을 찾아서 Optional<Reply>로 받아서 넣으려고 하면 타입이 맞지 않아 오류가 뜬다. 그래서 parentReply의 타입을 Optional로 받으려 했으나 불가하다고 나온다 ㅠ
728x90
반응형
'개인 프로젝트 > 블로그' 카테고리의 다른 글
댓글 수정 구현 + react에서 수정,삭제하기 (0) | 2022.07.31 |
---|---|
댓글 삭제 구현 로직 생각 및 구현 (0) | 2022.07.29 |
jpa 대댓글 삭제에 대한 고민 (0) | 2022.07.24 |
react 조건부 렌더링 (0) | 2022.07.23 |
jwt를 이용한 조건부 렌더링 처리 고민 (0) | 2022.07.19 |