[JPA] Spring JPA 트랜잭션 미설정으로 인한 알림 삭제 작업 실패

eunoia73·2025년 1월 27일

trouble shooting

목록 보기
11/16

❕문제 상황
알림 삭제 기능을 개발하던 중 발생했다

❗️ 에러 문구
org.springframework.dao.InvalidDataAccessApiUsageException: No EntityManager with actual transaction available for current thread - cannot reliably process 'remove' call

  • JPA에서 트랜잭션 없이 remove (삭제) 작업을 실행하려 할 때 발생하는 오류
  • 트랜잭션이 없으면 EntityManager가 정상적으로 작동하지 않아 데이터 삭제가 수행되지 않는다.
  • JPA는 영속성 컨텍스트를 통해 엔티티를 관리한다.
    영속성 컨텍스트 - 엔티티 객체를 1차 캐시에 저장하고, 트랜젝션이 끝날 때 데이터베이스에 반영
  • JPA는 트랜젝션 단위로 데이터베이스와의 작업을 처리한다.
    트랜젝션이 없으면 데이터 변경작업(insert, update, delete)를 수행할 수 없다.

💡 가능한 해결 방법

명시적으로 EntityManager를 사용하여 트랜잭션 관리

  • EntityManager를 직접 사용하여 트랜젝션을 시작하고 커밋, 롤백을 명시적으로 처리하는 방법
    ❗️ 더 많은 코드와 명시적 관리가 필요하므로 일반적으로 권장되지 않는다.
//예시 코드
@PersistenceContext
private EntityManager entityManager;

public boolean deleteNotification(String notificationId) {
    entityManager.getTransaction().begin();
    Notification notification = entityManager.find(Notification.class, notificationId);
    if (notification != null) {
        entityManager.remove(notification);
        entityManager.getTransaction().commit();
        return true;
    } else {
        entityManager.getTransaction().rollback();
        return false;
    }
}

✅ 선택한 해결 방법

@Transactional 어노테이션 추가 방식

  • Spring JPA의 표준적인 트랜잭션 관리 방식이다.
  • 코드가 간결하고 직관적이며, 효율적이다.
    -> notificaitonService의 deleteNotification에 @Transactional을 추가한다.
    //알림 삭제
    @Transactional
    public boolean deleteNotification(String userNickname, String notificationId) {
        // 알림 조회

        Optional<Notification> notification = notificationRepository.findByNotificationId(notificationId);

        if (notification.isPresent() && notification.get().getReceiver().equals(userNickname)) {
            // 알림이 존재, receiver와 user nickname같으면 삭제
            int result = notificationRepository.deleteByNotificationId(notificationId);
            if (result == 1) {
                log.info("result={}", result);
                return true;
            } else return false;
        }

        // 알림이 존재하지 않는 경우
        return false;
    }

0개의 댓글