본문 바로가기

Spring Boot/Spring Boot

58 : 답글 구현하기 (SpringbootApi + JPA)

답글 구현하기의 Service 부분과, 쿼리를 구현하는 Repository 부분을 실행 순서에 따라 다룬 글이다

Repository의 코드는 (BoardRepository)로 표시 

 

PostMan에서 값을 넣고 Send하면 아래의 순서대로 실행

 


1. ID 값 체크

1-1

입력한 id로 해당하는 테이블 글정보 불러온다

-> 입력한 id로 검색한 값이 DB에 없으면 -> 예외 출력한다. 

@Transactional
    public ApiResponse<BoardDTO> postReply(BoardDTO dto) {
        /* JPQL TEST 겸 원글 불러오기 */
        Board b = boardRepository.selectBoard(dto.getId());
        if(b == null){
            return new ApiResponse(false, "board id " + dto.getReplyRootId() + " is null");
        }

아래 쿼리는 입력한 id에 해당하는 글이 있는지 없는지 확인하는 쿼리이다.

(BoardRepository)

    // JPQL != SQL
    @Query("Select b FROM Board b where b.id = ?1") // JPA를 이용하여 쿼리를 날린다.
    Board selectBoard(int id);
    //model에 있는 board를 가리킨다
    //JPA에서 sql을 사용하고싶을때

 

1-2

입력한 dto에서 아래 답글의 순서와 위치를 정하는 값을 들고온다.

        /* depth와 orderNum을 정하는 로직 START */
        int replyRootId = dto.getReplyRootId();
        int depth = dto.getDepth();
        int orderNum = dto.getOrderNum();

 

 

 


2. minOrderNum 구하기

minOrderNum은 답글 사이에 추가되는 글인지, 맨 밑에 달리는 글인지 확인하는 역할

        Integer minOrderNum = boardRepository.getMinOrderNum(replyRootId, depth, orderNum);
        if(minOrderNum == null) {
            minOrderNum = 0;
        }

 

아래 쿼리는 MinOrderNum을 구하는 쿼리

JPQL에서는 NVL이 지원이 안돼서 null처리를 위와같이 코드로 구현

  • MinOrderNum = Null이면 0
  • 아니면 조회한 값을 가진다.

(BoardRepository)

    @Query("SELECT MIN(b.orderNum) FROM Board b" +
            "                WHERE  b.replyRootId = ?1" +
            "                AND b.orderNum > ?3" +
            "                AND b.depth <= ?2")
    Integer getMinOrderNum(int replyRootId, int depth, int orderNum);

 

 

 


3. minOrderNum 의 if문

minOrderNum의 값에따라 if문이 실행된다.

        if(minOrderNum == 0) {
            log.debug("======root글에 달린 답글들 사이에 추가되는 답글이 아님(바로추가답글)======");
            orderNum = boardRepository.getReplyOrderNum(replyRootId);
        } else {
            log.debug("======root글에 달린 답글들 사이에 추가되는 답글.(사이답글)======");
            boardRepository.updateOrderNum(replyRootId, minOrderNum);
            orderNum = minOrderNum;
        }

 

만약 이 0이면 아래와 같은 쿼리를 실행한다.

입력한 rootId 값 중 제일 큰 orderNum 값에 +1 (제일 마지막 순서) 

(BoardRepository)

    @Query("SELECT MAX(orderNum) + 1 FROM Board" +
            " WHERE replyRootId = ?1")
    Integer getReplyOrderNum(int replyRootId);

 

이 0이 아니면 답글 사이에 추가되는 글이므로 아래의 Update쿼리를 실행한다.

  • 같은 rootId의 3번글에서 조회한 값보다 크거가 같은 모든 orderNum을 +1

(BoardRepository)

    @Modifying
    @Transactional
    @Query("UPDATE Board SET orderNum = orderNum + 1" +
            "                WHERE replyRootId = ?1  AND orderNum >= ?2")
    void updateOrderNum(int replyRootId, int minOrderNum);

update 와 delete 의 JPQL에는 @Modifying @Transactional 어노테이션 두개를 붙혀줘야 한다.

 

 

 


4. 답글의 깊이 구하기

답글이므로 글의 깊이를 +1 하고, 깊이에 따라 글 앞에 "RE : "를 붙인다

        int newDepth = depth + 1;
        log.debug("newDepth=" + newDepth);
        String newSubject = appendPrefixString("RE : ", depth, dto.getSubject());
        /* depth와 orderNum을 정하는 로직 END */

appendPrefixString 은 깊이의 값 만큼 "RE : " 를 붙여주는 역할을 한다

    private String appendPrefixString(String appendPrefix, int loop, String target) {
        StringBuilder builder = new StringBuilder();
        for(int i=0; i<=loop; i++){
            builder.append(appendPrefix);
        }
        builder.append(target);
        return builder.toString();
    }