@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 = ?