본문 바로가기
개발/문제 해결

JPA Custom Query Method 사용 시 트랜잭션 이슈 및 해결

by nineteen 2025. 2. 24.
반응형

문제 상황

  • JPA Repository에서 커스텀 쿼리 메소드로 데이터를 삭제하려 했을 때 트랜잭션 관련 예외가 발생하였습니다.
  • 구체적으로는 No EntityManager with actual transaction available for current thread 에러가 발생하였습니다.
  • 특이한 점은 JPA에서 기본으로 제공하는 delete 메소드들(deleteById, delete 등)은 정상적으로 동작하였으나, 커스텀 메소드에서만 문제가 발생하였습니다.

원인

  • JPA의 SimpleJpaRepository에서 제공하는 기본 삭제 메소드들에는 @Transactional 어노테이션이 기본적으로 포함되어 있습니다.
  • 실제 SimpleJpaRepository의 구현부를 보면 다음과 같이 모든 삭제 메소드에 @Transactional이 붙어있는 것을 확인할 수 있습니다:
@Repository
class SimpleJpaRepository<T, ID> : JpaRepository<T, ID> {
    @Transactional
    override fun delete(entity: T) {
        // ... 구현부 생략 ...
    }

    @Transactional
    override fun deleteById(id: ID) {
        // ... 구현부 생략 ...
    }
}
  • 반면에 커스텀 쿼리 메소드는 @Transactional 어노테이션이 없는 상태로 생성됩니다.
  • Service 레이어에도 @Transactional이 없는 상태였기 때문에 트랜잭션 컨텍스트가 생성되지 않았던 것이 문제였습니다.

해결 방법

Repository

// AS-IS: 트랜잭션 어노테이션이 없는 상태
interface UserRepository : JpaRepository<User, Long> {
    fun deleteAllBySeqIn(userSeqList: List<Long>)
}

// TO-BE: 트랜잭션 어노테이션 추가
interface UserRepository : JpaRepository<User, Long> {
    @Transactional
    fun deleteAllBySeqIn(userSeqList: List<Long>)
}