문제1
public void deleteFriend(Long userId) {
friendRepository.findByIdAndSetStatusDeleted(userId);
}
친구를 삭제하고 싶을 때 전달받은 유저의 id로 해당 테이블에서 데이터를 조회하고, 그 데이터의 Status 값을 DELETED로 변경하고자 했다.
Spring Data JPA는 메서드명을 주어진 형식으로 사용해야 자동으로 JPA가 DB에 데이터를 처리해줄 수 있다.
위 코드처럼 findByIdAndSetStatusDeleted 같이 명확하지 않으면서 형식으로 주어지지 않은 메서드명은 사용할 수 없었다.
해결
먼저 테이블에서 내가 원하는 데이터를 가져오려면 로그인한 유저와 상대 유저의 id가 모두 있어야 했다.
그러므로 findByReceiverAndRequester를 사용해서 두 유저 자체를 레포지토리에 전달해서 해당하는 객체를 반환받았다.
그리고 반환받은 객체의 Status 필드를 변경 감지를 통해 변경하도록 코드를 수정했다.
User receiver = userRepository.findById(loginedUserId).orElseThrow(NoSuchElementException::new);
User requester = userRepository.findById(userId).orElseThrow(NoSuchElementException::new);
// 상대 유저가 requester, 로그인 유저가 receiver인 friendRequest 반환
FriendRequest foundFriendRequest = friendRepository.findByReceiverAndRequester(receiver, requester).orElseThrow(NoSuchElementException::new);
// Status가 PENDING 상태인 경우 ACCEPT로 변경
if (foundFriendRequest.getStatus() == PENDING) {
foundFriendRequest.setStatus(ACCEPT);
}else {
// Status가 PENDING이 아닌 경우 예외 발생(이미 요청을 거절, 수락하거나 친구 삭제한 경우)
throw new AlreadyProcessedException();
}
문제2
user1과 user2를 사용해서 레포지토리에서 데이터를 반환하려고 할 때, 두 유저 모두 receiver 또는 requester가 될 수 있는 상황이라 양방향으로 체크해야 했다.
이 경우는 user1이 receiver일 때와, user2가 receiver일 때를 각각 조회해야 하는지 고민을 했던 것 같다.
해결
이런 상황은 직접 쿼리를 작성하는데 더 효율적인 방식인 것 같아서 검색해보니 JPQL을 사용하면 쉽게 해결할 수 있었다.
JPQL은 엔티티 객체를 기준으로 쿼리를 작성하는 방법이다.
테이블 이름, 컬럼 이름이 아니라 엔티티 이름과 필드 이름을 사용한다.
@Query("select f from FriendRequest f where (f.receiver = :loginedUser and f.requester = :friend)"
+ "or (f.receiver = :friend and f.requester = :loginedUser)")
Optional<FriendRequest> findInteractiveRequest(@Param("loginedUser") User loginedUser, @Param("friend")User friend);
@Query 어노테이션을 통해 내 의도대로 쿼리를 작성한다.
그리고 기존에 JDBC template을 사용할 때 ?로 prepared 방식으로 sql문을 사용했던 것과 유사하게, @Param과 :을 사용해서 파라미터를 바인딩한다.
만약 엔티티, 필드명이 아니라 실제 데이터베이스의 테이블 이름과 컬럼 이름을 사용하고 싶다면 @Query 어노테이션의 속성으로 nativeQuery=true로 설정하면 된다.
'트러블 슈팅' 카테고리의 다른 글
리스트 타입 필드는 @NotBlank 대신 @NotEmpty (2) | 2025.04.14 |
---|---|
직렬화 실패 이슈 해결 (0) | 2025.04.10 |
[Java/Spring] Filter 내부의 예외처리 (0) | 2025.04.03 |
[Java/Spring] 분리된 테이블의 데이터 반환 트러블 슈팅 (+레이어 리팩토링) (0) | 2025.03.25 |
[Java/Spring] 406 Not Acceptable / 검증 어노테이션 에러 메시지 변경 (0) | 2025.03.24 |