Hibernate는 연관된 엔터티 상태 작업의 순서대로 SQL 문을 실행하지 않습니다.
다음과 같은 코드가 있다고 예상할 경우
Person person = entityManager.find(Person.class, 1L);
entityManager.remove(person);
Person newPerson = new Person();
newPerson.setId(2L);
newPerson.setName("John Doe");
entityManager.persist(newPerson);
저희는 DELETE 질의 이후 INSERT 질의를 기대 합니다.
하지만 동작은 아래와 같습니다.
INSERT INTO Person (name, id)
VALUES ('John Doe', 2L)
DELETE FROM Person WHERE id = 1
SQL 문이 실행되는 순서는 엔티티의 상태 변화가 아닌, ActionQueue
에 의해서 지정됩니다.
ActionQueue에서는 다음 순서로 모든 작업을 실행합니다 .
- OrphanRemovalAction
- EntityInsertAction또는EntityIdentityInsertAction
- EntityUpdateAction
- QueuedOperationCollectionAction
- CollectionRemoveAction
- CollectionUpdateAction
- CollectionRecreateAction
- EntityDeleteAction
만약, 꼭 삭제를 먼저 실행하고 싶다면 다음과 같이 강제로 flush를 호출 해야 합니다.
Person person = entityManager.find(Person.class, 1L);
entityManager.remove(person);
entityManager.flush(); // 강제 flush로 SQL 실행
Person newPerson = new Person();
newPerson.setId(2L);
newPerson.setName("John Doe");
entityManager.persist(newPerson);
마치며
이 부분을 잘 이해 못해서 삽질을 오래 하였습니다.
강제로 flush 하기 보다 OrphanRemovalAction
를 활용하여 처리 하는게 좋게 보여지기도 합니다.