- [트러블 슈팅] JPA UPDATE 벌크 연산 후 조회 안됨2026년 02월 01일 14시 14분 58초에 업로드 된 글입니다.작성자: do_hyuk728x90반응형
기존 코드
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = {Exception.class}, transactionManager = "ncpTransactionManager") public void testMethod(String ranId, String uId) { jpaRepository.save(entity); ... mybatisDao.softDeleteAll(ranId); }Jpa에서는 saveAll() 과 같은 벌크 연산을 update에는 제공해주고 있지 않기 때문에 다수의 업데이트 쿼리를 방지하고자 사용
단일 쿼리 INSERT INTO table (col1, col2...) VALUES (val1, val2...); INSERT INTO table (col1, col2...) VALUES (val1, val2...); INSERT INTO table (col1, col2...) VALUES (val1, val2...); 벌크 연산 INSERT INTO table (col1, col2...) VALUES (val1, val2...), (val1, val2...), (val1, val2...);문제 상황
@Transactional 옵션에서 사용한 트랜잭션 매니저는 JPA 전용이다.
그렇기 때문에 myBatis는 해당 트랜잭션을 함께 공유하지 못하기 때문에 Exception 발생 후 롤백이 일어날 때 myBatis 로 실행한 쿼리는 롤백되지 않는 문제가 발생할 것이다.
1차 수정 코드
@Modifying() @Query("UPDATE TestEntity t SET t.isDelete = 'Y' WHERE t.idx =:idx") void softDeleteAll(@Param("idx") Long idx);@Modifying 어노테이션은 Spring Data JPA에서 사용하는 어노테이션으로, @Query 어노테이션을 통해 작성된 변경이 일어나는 쿼리(INSERT, DELETE, UPDATE)를 실행할 때 사용된다.
벌크 연산은 데이터베이스에서 대량의 데이터를 한 번에 처리하기 위한 작업이기 때문에 JPA에서 벌크 연산은 단 건 데이터를 변경(더티 체킹)하는 것이 아닌, 여러 데이터에 변경 쿼리를 날리는 작업이다.
1차 테스트 결과
DB에 데이터 변경이 성공적으로 된 것을 확인.
이 후 jpaRepository.findById(idx) 메서드로 조회했지만 결과가 수정 전 데이터와 같다는 것을 확인하게 됨
문제 원인
JPA 에서는 영속성 컨텍스트에 있는 1차 캐시를 통해 엔티티를 캐싱하고, DB의 접근 횟수를 줄임으로써 성능 개선 한다.
JPA 에서 조회를 실행할 시에 1차 캐시를 확인해서 해당 엔티티가 1차 캐시에 존재한다면 DB 에 접근하지 않고, 1차 캐시에 있는 엔티티를 반환한다.
하지만 벌크 연산은 1차 캐시를 포함한 영속성 컨텍스트를 무시하고 바로 Query를 실행하기 때문에 영속성 컨텍스트는 데이터 변경을 알 수가 없다.
즉, 벌크 쿼리를 실행하기 전에 영속성으로 관리되던 객체가 있었을 때 조회 시 영속성 컨텍스트에 과거 값이 남아 1차 캐시와 DB의 데이터 싱크가 맞지 않게 되는 것이다.
문제 해결
변경된 데이터를 사용하기 전에 영속성 컨텍스트를 비워주는 작업이 필요
@Modifying의 옵션 중 clearAutomatically=true 속성을 사용해서 영속성 컨텍스트를 초기화 할 수 있다.
(조회를 실행할 때 1차 캐시에 해당하는 엔티티가 존재하지 않기 때문에 DB 조회 쿼리를 실행하게 된다.)
@Modifying(clearAutomatically = true) @Query("UPDATE TestEntity t SET t.isDelete = 'Y' WHERE t.idx =:idx") void softDeleteAll(@Param("idx") Long idx);728x90반응형'Spring' 카테고리의 다른 글
[트러블 슈팅] 다중 인스턴스일 때 동시성 문제 해결 (0) 2026.03.08 Spring Cache 사용기록 (0) 2026.02.22 [트러블 슈팅] 재배포 없이 스케줄링 날짜 변경하기 (0) 2026.01.31 [트러블 슈팅] JWT 유효기간보다 빨리 만료되는 문제 해결 (0) 2026.01.11 Chained Transaction Manager deprecated (0) 2026.01.04 댓글