해결된 질문
작성
·
343
0
오랜만에 관련된 업무 진행하다가 발생한 궁금점에 대하여 질문드리게 되었습니다. 우선 한 트랜젝션의 영속성 컨텍스트에 대하여 쓰기 지연 저장소에 쌓인 쿼리가 flush() 되는 경우는 다음 세 가지로 이해하였습니다.
flush() 직접호출
트랜젝션 commit()
JPQL 직접 발생시, 해당 JPQL 발생 이전
다음과 같은 연관관계가 가정되어 있다고 해보겠습니다.
public class Car{
@Id
private Long id;
}
public class Wheel {
@Id
private Long id;
@ManyToOne
@JoinColumn(name = "car_id")
private Car car;
}
Wheel 이 연관관계의 주인이며, Car 와 M:1 관계로 매핑되어 있습니다.
이 때, 다음과 같은 로직을 수행해보겠습니다. (1L 의 Wheel 이 2L 의 Car 에 매핑되어 있음)
Wheel wheel = em.find(Wheel.class, 1L);
wheel.setCar(null); // 1)
em.createQuery("delete from Car c where c.id = :id")
.setParameter("id", 2L)
.exeucteUpdate(); // 2)
이와 같이 수행되었을 때,
1번 시점에서 영속성 컨텍스트에 보관중인 Wheel 의 Car 값이 변경되어 Update 쿼리가 발생하여 쓰기 지연 저장소에 저장되었을 것으로 추측합니다.
2번 시점은 위에서 말한 'flush 발생시점' 중 3번에 해당한다고 생각했습니다 (JPQL 직접 수행). 그렇다면 쓰기 지연 저장소에 쌓인 Update 쿼리가 나간 이후, 직접 수행하려는 Delete JPQL 을 발생시켜서 아무 문제 없이 수행되어야 하는거 아닌가 싶었는데, 위 로직은 FK 제약조건에 위배되어 수행되지 못합니다.
1번과 2번 사이에 강제로 em.flush() 를 진행해주면, 그제서야 update 쿼리가 발생한 뒤에 delte 쿼리가 발생하여 위 로직이 아무 에러 없이 수정되는 모습을 확인했습니다.
왜 이 상황에서는 flush 가 자동으로 발생하지 않나요? 열심히 찾아봤을 때... JPA 측에서 제공하는 3번 (JPQL 발생시 flush 됨) 에 대한 명확한 [기준] 은 제시하고 있지 않은 것으로 보이는데 맞을까요??