- 문제
@Query + @Modifying를 활용해 업데이트 벌크 연산을 진행했는데, Auditing + @LastModifiedDate가 작동하지 않는 것을 확인했다.
1. Auditing과 @LastModifiedDate을 적용하고 10개의 임의 데이터를 추가한다.
2. @Query + @Modifying을 활용한 벌크 연산을 진행한다.
- ShibaRepository
@Modifying(clearAutomatically = true)
@Query("update Shiba s set s.age = :age where s in (:shibaList)")
int updateAllShibaAge(@Param("age") Integer age, @Param("shibaList") List<Shiba> shibaList);
- ShibaRepositoryTest
@Test
@Transactional
@Rollback(value = false)
void checkBulkUpdate() {
List<Shiba> shibaList = shibaRepository.findAll();
shibaRepository.updateAllShibaAge(20, shibaList);
}
테스트 결과, age 필드는 업데이트가 정상적으로 됐지만 날짜는 변경되지 않는 것을 확인할 수 있었다.
3. 변경 감지를 통한 업데이트를 진행한다.
그렇다면, dirty checking(변경 감지)를 활용해서 업데이트를 하면 어떨까?
@Test
@Transactional
@Rollback(value = false)
void checkBulkUpdateByDirtyChecking() {
List<Shiba> shibaList = shibaRepository.findAll();
shibaList.forEach(i -> i.updateAge(30));
}
변경 감지를 통한 업데이트를 진행했을 때는 정상적으로 날짜가 업데이트 된 것을 확인할 수 있었다.
- 원인
Auditing은 도메인을 영속성 컨텍스트에 저장하거나 조회를 수행한 후에 update를 하는 경우 자동으로 시간을 매핑하여 데이터베이스 테이블에 넣어주는 방식으로 작동한다.
하지만 @Query로 정의된 벌크 연산 JPQL은 기존 JPA 처럼 영속성 컨텍스트를 거쳐 쓰기지연 SQL로 동작하지 않고, 직접 DB와 쿼리하기 때문에 Auditing 기능이 적용되지 않았다.
- 해결
@Query 구문에 시간을 직접 업데이트 하는 방식으로 해결했다.
@Modifying(clearAutomatically = true)
@Query("update Shiba s set s.age = :age, s.updatedAt = :updatedAt where s in (:shibaList)")
int updateAllShibaAge(@Param("age") Integer age, @Param("updatedAt") LocalDateTime updatedAt, @Param("shibaList") List<Shiba> shibaList);
직접 업데이트할 때 LocalDateTime.now() 파라미터를 추가하여 시간을 저장한다.
@Test
@Transactional
@Rollback(value = false)
void checkBulkUpdate() {
List<Shiba> shibaList = shibaRepository.findAll();
shibaRepository.updateAllShibaAge(40, LocalDateTime.now(), shibaList);
}
테스트 결과, 날짜가 정상적으로 업데이트 되는 것을 확인할 수 있었다.
'Spring > JPA' 카테고리의 다른 글
Spring Boot 3.0 QueryDsl Maven 설정하기 (0) | 2023.04.09 |
---|---|
JPA 동일 트랜잭션에서 update와 insert 동시에 수행할 때 문제 해결하기 (쿼리 실행 순서 문제) (0) | 2023.02.05 |
JPA @Where 일괄 조회 사용법 및 문제점과 해결방안 (0) | 2023.01.24 |
JPA @Query @Modifying 벌크 삭제 연산시 연관관계 문제 해결하기 (with SQLIntegrityConstraintViolationException) (0) | 2023.01.22 |
JPA, ORM 그리고 패러다임의 불일치 (0) | 2022.07.24 |
댓글