🚨 에러가 발생한 상황
투표 취소 API를 테스트 하던 중에 아래에 적힌 에러가 발생했다.
No EntityManager with actual transaction available for current thread - cannot reliably process 'remove' call
문제가 일어난 코드는 아래와 같다.
public void cancel(
final Long voteId,
final Long memberId
) {
final Vote vote = voteReader.read(voteId);
if (voterRepository.existsByVoteAndMemberId(vote, memberId)) {
voterRepository.deleteByVoteAndMemberId(vote, memberId);
}
}
✅ 에러 해결
에러를 읽어보니 사용가능한 트랜잭션을 가진 EntityManager가 없어서 'remove'를 할 수 없다고 한다. 이게 무슨 말인가 찾아보니 쓰기를 수행하는 메서드에는 @Transactional을 붙여줘야 한다는 것이다.
내가 작성한 메서드에는 @Transactional을 붙여주지 않아서 생긴 문제였다. @Transactional을 붙여주니까 에러는 해결됐다.
🐾 쿼리 메서드의 @Transactional
우리가 평소 사용하는 JpaRepository의 구현체는 SimpleJpaRepository이다. SimpleJpaRepository의 코드를 보면 조회 메서드를 제외하고 deleteXXX, saveXXX 메서드들에 모두 @Transactional이 붙어있는 것을 확인할 수 있다.
하지만 개발자가 정의한 쿼리 메서드에는 @Transactional이 붙어있지 않아서 직접 붙어줘야한다.