답글 구현하기의 Service 부분과, 쿼리를 구현하는 Repository 부분을 실행 순서에 따라 다룬 글이다
Repository의 코드는 (BoardRepository)로 표시
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();
}
'Spring Boot > Spring Boot' 카테고리의 다른 글
60 : SpringbootApi 관련 질문 (0) | 2021.11.03 |
---|---|
59 : jar & war 파일로 빌드하기 (0) | 2021.11.02 |
56 : 복수의 트랜잭션으로 Comment 처리 (Springboot + JPA) (0) | 2021.10.27 |
55 : JPA+Pageable 페이징처리 (Springboot + JPA) (0) | 2021.10.26 |
53 : JPA로 삭제와 리스트 출력 review (Springboot + JPA) (0) | 2021.10.26 |