Spring/[P] AI 챗봇 기반 맞춤형 레시피 서비스

[SpringBoot/Querydsl] QnA 대댓글 (2) 작성

alsruds 2024. 3. 4. 17:32

 

대댓글 형식의 QnA 를 작성해봅시다 ~

 

 


 

[ QnA 작성하기 ]

 

0. Querydsl 설정

2024.03.01 - [Spring/[Project] AI 챗봇 기반 맞춤형 레시피 서비스] - [SpringBoot/Querydsl] 대댓글 Querydsl (1) 프로젝트 설정

 

[SpringBoot/Querydsl] QnA 대댓글 (1) Querydsl 프로젝트 설정

스프링부트 프로젝트에서 Querydsl - jpa 을 사용할 수 있도록 프로젝트 설정을 해봅시다 ~ [ SpringBoot 프로젝트 설정하기 ] 0. Querydsl 공식 문서 🏠 http://querydsl.com/

alsrudalsrudalsrud.tistory.com

 

1. Entity

@Entity
@Getter
@Builder
@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Qna extends BaseEntity {

    ...

    // 부모 댓글 : null 일 경우 최상위 댓글
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "parent_id")
    private Qna parent;

    // 자식 댓글들
    @OneToMany(mappedBy = "parent", orphanRemoval = true)
    private List<Qna> children = new ArrayList<>();

    // 삭제 여부
    @ColumnDefault("FALSE")
    private Boolean isDeleted;

    public void updateParent(Qna qna) {
        this.parent = qna;
    }
}

 

· Entity 에 부모와 자식 댓글 컬럼을 같이 만들어주기!

 

2. Controller

@RestController
@RequestMapping("/post")
@RequiredArgsConstructor
public class QnaController {

    private final QnaService qnaService;

    // Qna 작성
    @PostMapping(value = "/{postId}/qna", consumes = "multipart/form-data")
    public ApiResponse<QnaResponseDTO.addQnaDTO> addQna(@PathVariable("postId") Long postId,
                                                             @RequestPart(name = "QnaRequestDTO", required = false) QnaRequestDTO.addQna request,
                                                             @RequestPart(value = "file", required = false) MultipartFile file) throws IOException {
        // 작성자
        String memberId = SecurityContextHolder.getContext().getAuthentication().getName();

        Qna qna = qnaService.addQna(memberId, postId, request, file);
        return ApiResponse.onSuccess(QnaConverter.addQnaResult(qna));
    }
}

 

· 저장할 데이터 서비스 로직에 넘겨주기

 

3. Service

@Service
@RequiredArgsConstructor
@Transactional
@Slf4j
public class QnaServiceImpl implements QnaService {

    private final MemberRepository memberRepository;
    private final PostRepository postRepository;
    private final QnaRepository qnaRepository;
    private final S3Service s3Service;

    // Qna 작성
    @Override
    public Qna addQna(String memberId, Long postId, QnaRequestDTO.addQna request, MultipartFile file) throws IOException {

        ...

        // 저장할 데이터 세팅
        Qna qna = QnaConverter.toQna(member.get(), post, request, imageUrl, fileName);

        // 자식 댓글이면, 부모 댓글 업데이트
        Qna parentQna;
        if (request.getParentId() != 0) {
            parentQna = qnaRepository.findById(request.getParentId()).orElseThrow(() -> new GeneralException(ErrorStatus.POST_QNA_NOT_FOUND));
            qna.updateParent(parentQna);
        }

        return qnaRepository.save(qna);
    }
}

 

· 데이터 저장하기 (자식 댓글일 시 부모 댓글 업데이트 → parentId 로 구분 가능)

 

4. Repository

public interface QnaRepository extends JpaRepository<Qna, Long> {}

 

· JpaRepository 기능으로 데이터 저장하기

 

5. DTO

public class QnaRequestDTO {

    @Schema(description = "Qna 신규 등록 요청 DTO")
    @Builder
    @Getter
    @NoArgsConstructor
    @AllArgsConstructor
    public static class addQna {
        @Schema(description = "Qna 내용", defaultValue = "설탕 대신 알룰로스를...")
        private String content;
        @Schema(description = "부모 댓글 Id", defaultValue = "0")
        private Long parentId;
    }
}

 

· 데이터 입력받을 때, parentId 같이 입력받기 ( 0 이면 질문 댓글, 다른 id 값이면 답변 댓글 )