Java & Spring

업데이트 쿼리에서 발생하는 TransactionRequiredException

ju_young 2024. 5. 17. 16:13
728x90
@Modifying  
@Query("update Alarm a set a.readAt = now() where a.id = ?1")  
void updateReadAtById(Long alarmId);

위와 같이 알람의 readAt 속성 값을 현재 일시로 업데이트하는 쿼리메소드를 실행하면 다음과 같은 예외가 발생한다.

 

TransactionRequiredException: Executing an update/delete query

@Transactional

예외를 해결하기위해서 @Transactional을 추가해주면 된다.

@Transactional
@Modifying  
@Query("update Alarm a set a.readAt = now() where a.id = ?1")  
void updateReadAtById(Long alarmId);

그런데 Transaction 이 필요없음에도 @Transactional을 추가해주어야하는 걸까?

 

위 쿼리 메소드는 로그인한 사용자가 알람을 읽었을 때 읽은 일시로 업데이트하기위해 사용한다. 따라서 여러 사용자가 해당 메소드를 통해 쿼리를 요청할 일이 없다고 판단했기 때문에 Transaction 또한 필요없다고 판단한 것이다.

 

그렇다면 Transaction을 추가하지 않으려면 어떻게 해야할까?

Native Query

@Query(nativeQuery = true, value = "update alarms a set a.read_at = now() where a.id = ?1")  
void updateReadAtById(Long alarmId);

위처럼 native query를 사용하여 update를 요청하게되면 jpa를 통해 쿼리가 실행되지 않기때문에 Transaction이 적용되지 않아도 예외가 발생하지 않는다.

 

로그를 확인해보면 EntityManager를 생성하고 요청하는 것을 확인할 수 있다.

2024-04-16 19:33:31.826 DEBUG 12819 --- [nio-8080-exec-2] tor$SharedEntityManagerInvocationHandler : Creating new EntityManager for shared EntityManager invocation
Hibernate: 
    update
        alarms a 
    set
        a.read_at = now() 
    where
        a.id = ?
728x90