Post

TIL(20240714) [프론트 드래그앤드롭 - 카드 순서이동/ 카드 작업자별 조회]


카드순서이동- 드래그앤드롭 시연영상

먼저 위 영상을 보고 오면 DB 결과가 이해가 됩니다!

image

image

그리고 마무리 작업으로 카드 조회시 작업자별 조회 기능까지 구현해보았다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
@Repository
@RequiredArgsConstructor
public class CardCustomRepositoryImpl implements CardCustomRepository{

  private final JPAQueryFactory queryFactory;

  public List<CardResponseDto> findCardsInColumn(CardSearchCondDto searchCond) {
    QColumns column = QColumns.columns;
    QCard card = QCard.card;

    List<CardResponseDto> cardList = queryFactory
        .select(Projections.constructor(CardResponseDto.class, card))
        .from(card)
        .innerJoin(card.columns, column)
        .where(isWhere(searchCond))
        .limit(10)
        .fetch();

    return cardList;
  }


  private BooleanExpression isWhere (CardSearchCondDto searchCond) {
    BooleanExpression result = null;
    if(searchCond.getUsername().isEmpty()){
      throw new CustomException(ErrorEnum.USER_NOT_FOUND);
    }
    return result = card.user.name.eq(searchCond.getUsername());
  }
}

Query문에 대해서 코드 풀이를 해보자면 dto형태로 객체를 생성해서 가져오도록 하고 엔티티 기준으로 조회하여 card테이블에 있는 card의 column_id와 column 테이블을 묶어서 where에 해당하는 조건을 가져오도록 한다. 동적쿼리를 만들어..?보려고.. BooleanExpression을 사용했는데, 처음에는 전체조회/작업자별/카드상태별로 가져오려고 해당 쿼리를 저렇게 짰는데.. 지금 프론트랑 연결한 시점에서 전체조회와 카드상태별은 필요한 기능이 아닌거 같아서 작업자별로 조회하도록 수정했다.

service 쪽

1
2
3
4
5
6
7
 public List<CardResponseDto> getAllCards(CardSearchCondDto searchCond, Long userId) {
    User user = userRepository.findById(userId).orElseThrow(()-> new CustomException(ErrorEnum.USER_NOT_AUTHENTICATED));
    List<CardResponseDto> cardList = cardRepository.findCardsInColumn(searchCond);
    return cardList;
  }

controller

1
2
3
4
5
6
7
8
@GetMapping("/cards")
  public ResponseEntity<ApiResponse<List<CardResponseDto>>> getAllCards(@RequestBody CardSearchCondDto searchCond, @AuthenticationPrincipal UserDetailsImpl userDetails) {
    List<CardResponseDto> cardList = cardService.getAllCards(searchCond, userDetails.getUser().getId());
    ApiResponse<List<CardResponseDto>> response = new ApiResponse<>("카드 전체조회 성공", "200", cardList);
    return new ResponseEntity<>(response, HttpStatus.OK);
  }

유저를 넣고나서 테스트를 하는 과정에서 에러가 발생했는데, dto 생성자를 만드는 과정에서 뭔가 문제가 있는 듯 했다.

1
2
3
4
{
    "msg": "No constructor found for class com.sparta.trello.comment.dto.CommentResponseDto with parameters: [class com.sparta.trello.comment.entity.Comment]",
    "statuscode": 400
}

위와 같은 에러를 해결하기 위해서 찾아보니! 유저를 넣고 나서 유저의 매개변수를 넣어주지 않았던것!

이전

1
2
3
4
5
6
7
8
9
10
 List<CommentResponseDto> commentList = queryFactory
        .select(Projections.constructor(CommentResponseDto.class,
            comment))
        .from(comment)
        .where(comment.card.id.eq(cardId))
        .leftJoin(comment.card, card)
        .orderBy(comment.createdAt.desc())
        .offset(pageable.getOffset())
        .limit(pageable.getPageSize())
        .fetch();

수정

1
2
3
4
5
6
7
8
9
10
11
 List<CommentResponseDto> commentList = queryFactory
        .select(Projections.constructor(CommentResponseDto.class,
            comment,
            comment.user))
        .from(comment)
        .where(comment.card.id.eq(cardId))
        .leftJoin(comment.card, card)
        .orderBy(comment.createdAt.desc())
        .offset(pageable.getOffset())
        .limit(pageable.getPageSize())
        .fetch();

dto

1
2
3
4
5
6
7
8
9
public CommentResponseDto(Comment comment, User user) {
    this.cardId = comment.getCard().getId();
    this.message = comment.getMessage();
    this.createdAt = comment.getCreatedAt();
    this.updatedAt = comment.getUpdatedAt();
    this.username = user.getName();
  }

Projections.constructor를 사용할 때 주의할 점은 매개변수로 전달되는 필드 이름과 생성자의 매개변수 이름이 일치해야한다.

This post is licensed under CC BY 4.0 by the author.