리뷰 기능 IncorrectResultSizeDataAccessException: query did not return a unique result: 2;

Sol's·2023년 2월 14일
0

팀프로젝트

목록 보기
25/25

팀 프로젝트에서 모임을 하고 리뷰를 남기는 기능을 구현해야 했습니다.

이때 아래와 같은 에러가 발생했습니다.

IncorrectResultSizeDataAccessException: query did not return a unique result: 2;

조회한 값이 unique하지 않아서 발생한 에러입니다.

리뷰기능은 팀원이 맡은 로직이지만, Merge하는 과정에서
첫번째 참가자가 리뷰를 작성하면 두번째부터는 위와같은 에러를 발견했고
시간관계상 같이 로직을 수정해야 했습니다.

에러 원인

리뷰는 리스트 방식으로 저장이 되는데 1,2,3번이 있다고 하면
1번이 작성한 2,3 번에대한 리뷰가 리스트에 인덱스 [1], [2]으로 들어가고
2번이 작성한 1,3 번에대한 리뷰가 리스트에 인덱스 [3], [4]으로 들어가고
3번이 작성한 1,2 번에대한 리뷰가 리스트에 인덱스 [5], [6]으로 들어가서

조회를 하면 2개이상의 쿼리가 나오게 됩니다.

에러 코드

에러가 발생한 코드입니다.

// 리뷰 저장
    @Transactional
    public void addReview(ReviewRequest crewReviewRequest) {

        List<Review> reviewList = new ArrayList<>();

        try{
            Crew crew = crewRepository.findById(crewReviewRequest.getCrewId().get(0)).get();
            User fromUser = userRepository.findById(crewReviewRequest.getFromUserId().get(0)).get();

            for (int i = 0; i < crewReviewRequest.getCrewId().size(); i++) {
                Review review = new Review();

                User toUser = userRepository.findById(crewReviewRequest.getToUserId().get(i)).get();

                review.of(crew, fromUser, toUser,
                        crewReviewRequest.getUserMannerScore().get(i), crewReviewRequest.getUserReview().get(i));
                reviewList.add(review);
            }
            crewReviewRepository.saveAll(reviewList);

            // reviewScore 저장
            for (int i = 0; i < crewReviewRequest.getCrewId().size(); i++) {
                User toUser = userRepository.findById(crewReviewRequest.getToUserId().get(i)).get();
                Review review = crewReviewRepository.findReviewByCrewAndToUser(crew, toUser);
                toUser.addReviewScore(review.getReviewScore());
            }

        }catch (NullPointerException e){
            log.info("이용자 후기 NullPointerException : 작성 가능한 후기 내용이 없습니다.");
        }
    }

원인은 아래 코드였습니다.
3명 이상이 리뷰를 남기게 되면 서로 중복해서 리뷰를 남기기때문에 toUser가 2개 이상의 값을 갖게 되니 에러가 발생합니다.

Review review = crewReviewRepository.findReviewByCrewAndToUser(crew, toUser);

아래와 같이 쿼리문을 List형식으로 바꿔 에러를 해결하였습니다.
하지만 성능면에서 for문을 2번 사용하기때문에 좋은지는 좀 더 고민해 봐야겠습니다.

public interface CrewReviewRepository extends JpaRepository<Review, Long> {
    long countReviewByToUser(User user);
    List<Review> findAllByCrewAndToUser(Crew crew, User user);
}
// 리뷰 저장
    @Transactional
    public void addReview(ReviewRequest crewReviewRequest) {

        List<Review> reviewList = new ArrayList<>();

        try{
            Crew crew = crewRepository.findById(crewReviewRequest.getCrewId().get(0)).get();
            User fromUser = userRepository.findById(crewReviewRequest.getFromUserId().get(0)).get();

            for (int i = 0; i < crewReviewRequest.getCrewId().size(); i++) {
                Review review = new Review();

                User toUser = userRepository.findById(crewReviewRequest.getToUserId().get(i)).get();

                review.of(crew, fromUser, toUser,
                        crewReviewRequest.getUserMannerScore().get(i), crewReviewRequest.getUserReview().get(i));
                reviewList.add(review);
            }
            crewReviewRepository.saveAll(reviewList);

            // reviewScore 저장
            for (int i = 0; i < crewReviewRequest.getCrewId().size(); i++) {
                User toUser = userRepository.findById(crewReviewRequest.getToUserId().get(i)).get();
                List<Review> reviews = crewReviewRepository.findAllByCrewAndToUser(crew, toUser);
                for (Review review : reviews) {
                    toUser.addReviewScore(review.getReviewScore());
                }
            }

        }catch (NullPointerException e){
            log.info("이용자 후기 NullPointerException : 작성 가능한 후기 내용이 없습니다.");
        }
    }
profile
배우고, 생각하고, 행동해라

0개의 댓글