프로젝트에서 필요한 DELETE 쿼리를 만들기 위해,
다음과 같이 쿼리를 따로 작성하여 테스트하기 위해 @Query로 쿼리를 생성하고 @Transactional 어노테이션을 붙여 해당 작업을 트랜잭션 안에서 관리해주면 된다고 생각했다!
그래서 나는 벌크연산을 이용해 하나의 쿼리로 많은 데이터를 변경할 수 있도록 작성하였다.
@Transactional
@Query(value = "DELETE FROM BoardStorage bs \n" +
"WHERE bs.user.id = :user_id and bs.board.id in " +
"(SELECT b.id FROM Board b where b.user.id = :block_user_id)")
void deleteAllByUser_Id(@Param("user_id") Long user_id, @Param("block_user_id") Long block_user_id);
하지만 . . . 예상과는 달리 에러가 발생하였다.
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.InvalidDataAccessApiUsageException: org.hibernate.hql.internal.QueryExecutionRequestException: Not supported for DML operations [DELETE FROM..
검색을 통해 INSERT, UPDATE와 DELETE 쿼리에는 @Modifying 어노테이션을 추가해 주어야 한다는 것을 알 수 있었다.
@Modifying에 대해 알아보면,
- @Query를 통해 작성된 INSERT, UPDATE, DELETE (SELECT 제외) 쿼리에서 사용되는 어노테이션이다.
- 기본적으로 JpaRepository에서 제공하는 메서드 혹은 메서드 네이밍으로 만들어진 쿼리에는 적용되지 않는다.
- clearAutomatically, flushAutomatically 속성을 변경할 수 있으며 주로 벌크 연산과 같이 이용된다.
- JPA Entity Life-cycle을 무시하고 쿼리가 실행되기 때문에 해당 어노테이션을 사용할 때는 영속성 컨텍스트 관리에 주의해야 한다. (clearAutomatically, flushAutomatically를 통해 간단하게 해결할 수 있다.)
@Modifying과 @Query를 이용한 벌크 연산에서 주의할 점!
JPA에서 조회를 실행할 때, 1차 캐시를 확인해서 해당 엔티티가 1차 캐시에 존재한다면 DB에 접근하지 않고, 1차 캐시에 있는 엔티티를 반환한다. 하지만 벌크 연산은 1차 캐시를 포함한 영속성 컨텍스트를 무시하고 바로 Query를 실행하기 때문에 영속성 컨텍스트는 데이터 변경을 알 수 없다. 즉, 벌크 연산을 실행할 때 1차 캐시(영속성 컨텍스트)와 DB의 데이터 싱크가 맞지 않게 되는 것이다.
이를 해결하기 위해 @Modifying의 clearAutomatically를 true로 변경해준다면, 벌크 연산 직후 자동으로 영속성 컨텍스트를 clear 해준다. 그러면 조회를 실행하면 1차 캐시에 해당 엔티티가 존재하지 않기 때문에 DB 조회 쿼리를 실행하게 돼 데이터 동기화 문제를 해결할 수 있다.
즉, 벌크 연산 수행 후 영속성 컨텍스트를 초기화 해주어야 한다 !
참고 블로그 :
[Spring JPA] @Modifying 어노테이션
@Modifying 이란? @Query 어노테이션(JPQL Query, Native Query)을 통해 작성된 INSERT, UPDATE, DELETE (SELECT 제외) 쿼리에서 사용되는 어노테이션이다. 기본적으로 JpaRepository에서 제공하는 메서드 혹은 메서드 네
frogand.tistory.com
'Trouble Shooting' 카테고리의 다른 글
게시글 테이블과 게시글 이미지 테이블의 연관 관계 설정 (0) | 2023.11.11 |
---|---|
RDB vs NoSQL (0) | 2023.10.20 |
소셜 로그인, JWT 관련 의문점 정리 (0) | 2023.10.18 |
CI/CD 트러블 슈팅 (0) | 2023.07.25 |
Spring Boot 프로젝트 배포 자동화 설정 문제 해결 (0) | 2023.02.04 |