본문 바로가기

마주쳤던 이슈 기록

#6. 유저의 행동 횟수 조건 reset = Spring Data JPA 자동메서드

[에러]

현재 user가 특정 도서관에서 책을 대여하는데 최대 5권까지 대여가 가능한 조건을 걸어뒀다.

int rentalHistoryCount = memberBookRepository.countByMember(targetMember);

        if (rentalHistoryCount >= 5) {
            throw new BusinessLogicException(ExceptionCode.MAXIMUM_RENTAL_ALREADY);
        }
        targetLibraryBook.setBookStatus(Book.BookStatus.UNAVAILABLE);
        libraryBookService.saveLibraryBook(targetLibraryBook);

countByMember()메서드는 Spring Data JPA에서 제공하는 자동 메서드 형태
파라미터로 주어지는 member객체가 가진 MemberBook 엔티티의 수를 카운팅하는 역할이다.

하지만 유저가 5번 책을 대여한 뒤, 5번의 반납을 한 다음,
다시 대여를 요청하면 5번의 반납 사실이 카운팅되지 않고, 대여의 횟수만기록이 되는 에러가 발생.

[원인]

Spring Data JPA에서 제공하는 자동 메서드 성격 차이.
이 자동 메서드는 predefined method인 만큼,
모든 메서드들을 이름에 따라 그 동작을 알고 사용해야하지만 미숙함이 원인이었다.

[해결]

-기존-   countByMember(Member member)
MemberBook 테이블에서 전달된 member(memberId)와 연관된 row(가로행)을 카운팅한다.

MemberBook 엔티티 클래스에는 Member member 필드가 있는데
이 필드의 테이블 명은 memberId 라고 설정해두었다.

즉, countByMember(Member member)은 Spring Data JPA에서 사용하는 자동 메서드로써
실제 Spring Data JPA는 자동으로 countByMember(Member member)를 아래의 SQL 쿼리문으로 변경.

SELECT COUNT(*) FROM MemberBook WHERE memberId = ?

 

-개선-   countByMemberAndReturnedAtIsNull(Member member)
기존의 메서드에서 And로 추가적인 조건을 추가.

즉, MemberBook 테이블에서 파라미터로 전달되는 member(memberId)와 일치하는 row(가로행)에서 ReturnedAt 필드가 IsNull 인 row만 카운팅하는 메서드로 수정.
SQL 쿼리로 변경하게 되면

SELECT COUNT(*) FROM MemberBook WHERE memberId = ? AND returnedAt IS NULL;