schedule : 여러 명의 일정 담당 유저를 가질 수 있다.
user : 여러 개의 스케줄을 담당할 수 있다.
manage : 일정 테이블과 유저 테이블이 N:M 관계라 생성한 중간 테이블
이 중 일정을 작성한 유저는 추가로 일정 담당 유저들을 배치할 수 있습니다.
이 문구 때문에 일정을 수정하는 API 요청이 들어왔을 때, 추가로 배치할 담당 유저 리스트가 들어온다면 본래 존재하던 담당 유저를 삭제하고, 해당 리스트에 존재하는 유저들로 바꾸려고 했습니다.
그렇기 때문에
select)delete)select)insert)insert)와 같이 설계했습니다.
그러나 테스트를 해보니 이전 담당 유저의 삭제가 되지 않아 계속 데이터가 쌓이는 문제가 있었습니다.
여러번 코드를 수정하며 테스트해본 결과, delete 쿼리가 아예 날아가지 않거나, 모든 쿼리들이 실행된 후 마지막으로 실행되고 있음을 확인할 수 있었습니다.
각 로그의 시간을 보면 delete 쿼리가 insert 이후에 날아감을 확인할 수 있습니다.
설계한대로라면 select(schedule) → delete(manage) → select(user) → insert(manage) → update(schedule) 순서로 쿼리가 날아가야 하는데 왜 마지막에 delete 쿼리가 날아가지? 싶어서 동작 순서를 찾아보게 되었습니다.
하이버네이트에서는 아래와 같이 쿼리 실행 순서를 정해두었습니다.

@Transactional 어노테이션이 붙은 함수가 종료되면 쿼리문이 한꺼번에 실행되는데 하이버네이트에서 정해둔 우선순위에 따라 insert → update → delete 순으로 진행이 되기 때문에 여태 delete 쿼리가 마지막에 날아갔던 것이었습니다.
delete 쿼리 이후에 flush()를 호출해 바로 DB에 반영을 해주고,
이후에 insert 쿼리가 실행되도록 코드를 추가해주었습니다.
