인프런 커뮤니티 질문&답변

정규원님의 프로필 이미지
정규원

작성한 질문수

자바 ORM 표준 JPA 프로그래밍 - 기본편

영속성 컨텍스트 2

EntityManager의 쿼리 순서 보장

작성

·

181

0

1. 강의 내용과 관련된 질문인가요? 예
2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? 예
3. 질문 잘하기 메뉴얼을 읽어보셨나요? 예

[질문 내용]
안녕하세요. JPA의 영속성 컨텍스트의 쿼리 순서 보장에 대해 궁금한 점이 있어 연락드렸습니다.

@Transactional

public void deleteUser(Long userId) {

seniorRepository.findByUserId(userId).stream()

.forEach(seniorService::deleteSenior);

User user = findUserById(userId);

userRepository.delete(user);

}

 

senior 객체가 user객체를 외래키로 가지는 상태입니다.

user 객체를 삭제하고, senior 객체는 삭제하지 않기 위해서 위와 같은 코드를 작성하였습니다.

 

deleteSenior 메서드에서는 senior의 User 참조 값을 null로 바꾸어 주는 역할을 수행합니다.

그리고 같은 트랜잭션 내에서 user까지 삭제하는 코드입니다.

 

위 코드에서 senior의 User 참조 값을 null로 변경하는 update 로직과, user를 삭제하는 delete 로직이 트랜잭션이 종료된 시점에 한번에 쿼리로 생성되어 데이터베이스로 날아가는것이 맞는지 궁금합니다.

 

만약 그렇다면, 두 쿼리의 순서를 보장할 수 있는지 궁금합니다.

엔티티 매니저는 key-value 형태로 정보를 저장한다고 하여 순서가 보장되지 않을 것 같은데, 순서가 보장된다면 어떤 것에 의해서 순서가 보장되는지도 알려주시면 감사하겠습니다.


답변 1

0

안녕하세요, 인프런 AI 인턴입니다.

JPA의 영속성 컨텍스트는 플러시(flush)가 일어날 때, 즉 트랜잭션이 종료되는 시점에 변경 내역을 데이터베이스에 반영합니다. 이때 엔티티에 발생한 변경들은 순서대로 SQL로 변환되어 실행됩니다.

deleteSenior 메서드에서 senior 엔티티의 User 참조 값을 null로 변경한 후, 이어서 userRepository.delete(user)를 통해 user 엔티티를 삭제하면, JPA는 두 가지 작업을 순서에 맞게 처리합니다. 먼저 업데이트 쿼리로 senior 엔티티의 User 참조를 null로 변경하고, 다음으로 delete 쿼리로 user 엔티티를 삭제합니다.

이는 JPA가 내부적으로 엔티티의 생명주기(lifecycle)에 따른 쿼리들(insert, update, delete)을 모아두었다가 플러시 될 때, 정해진 순서로 발생시키기 때문에, 변경 감지가 일어난 업데이트 쿼리가 먼저 실행되고 이후에 삭제 쿼리가 실행됩니다. 순서는 보통 다음과 같습니다:

  1. insert
  2. update
  3. delete

그러므로, deleteSenior로 참조를 제거하고 userRepository.delete(user)로 삭제를 요청한 경우, 위에서 언급한 순서에 의해 참조 제거가 먼저 반영되고, 그 후에 삭제가 이루어지는 것이 일반적입니다.

JPA 표준 스펙에 따라 구현된 JPA 프로바이더(Hibernate 등)는 이 순서를 기본적으로 보장합니다. 그러므로 사용하시는 코드의 경우, deleteSenior를 통한 업데이트 작업과 userRepository.delete(user)를 통한 삭제 작업 순서가 JPA의 기본 순서에 따라 순차적으로 데이터베이스에 반영됩니다.

정규원님의 프로필 이미지
정규원

작성한 질문수

질문하기