JPA Query update @modifying
JPA를 사용하다보면 가끔 Bulk 업데이트를 위하여, query를 사용하여 업데이트 하는 경우가 있습니다.
그리고 이 경우, 우리는 항상 @modifying를 사용하게 됩니다.
그렇다면 어째서 @modifying를 사용해야만 하는것을까라는 궁금증이 생겼습니다.
그래서 @Query를 이용해서 업데이트 쿼리를 작성하되 @modifying를 사용, 미사용 상태로 돌려본 후, 결과를 지켜봤습니다.
우선 Repository interface에 @Modifying을 선언하지 않고 실행한 결과입니다.
@Component
public class JpaRunner implements ApplicationRunner {
@Autowired
private Repo repo;
@Transactional
@Override
public void run(ApplicationArguments args) throws Exception {
Account account = new Account();
account.setUsername("dusang");
account.setPassword("12354");
repo.save(account);
repo.updatePassword("testtest");
}
}
실행 러너 코드 이후 코드에서도 변경 X
public interface Repo extends JpaRepository<Account,Long> {
//@Modifying
@Query("UPDATE myAccount a SET a.password = ?1")
void updatePassword(String newPwd);
}
Repository @Modifying주석처리
매우매우 간단하게 세팅후, 실행을 해보면 다음과 같은 에러를 맞이하게 됩니다.
org.hibernate.hql.internal.QueryExecutionRequestException: Not supported for DML operations
해당 에러를 한번 추적해보면 다음과같은 QueryTranslatorImpl이라는 곳에서 에러가 발생시키고 있습니다.
그렇다면 주석을 해제하면..?🤔
다음과 같은 차이로 인하여 정상 실행이 되게 됩니다.
1. JpaQueryExecution 에서 호출하는 result = doExecute(query, accessor); 에서 이전과 다른 Execution 실행
@Modifying 적용시, ModifyingExecution, 미적용시 SingleEntityExecution 호출
2. 해당 Execution에서 처리하는 로직이 다른것을 실행하면서 결과적으로 Not supported for DML operations 미발생.
이번 포스팅은 @Modifying를 왜 사용해야하는가 라는 부분이 궁금해서 찾아본 글이였습니다.
요걸 찾아보면서 궁금했던점은 ModifyingExecution, SingleEntityExecution를 생성하는 부분, 주입하는 부분,어떤기준으로 execution이 갈리는지..?등에 대하여 확인할 예정입니다.