Auto Flush 조건
지금까지 알고있었던 자동 flush 조건은 셋 중 하나였다.
- em.flush() 호출
- 트랜잭션 Commit 시점
- JPQL 호출 직전
정말 JPQL 호출 직전 flush 할까?
눈으로 확인해보자.
JQPL 호출 직전 flush 한다면 쿼리의 순서는 INSERT -> SELECT -> SELECT 순이여야한다.
실제 쿼리를 확인해보자.
예상이 아주 기분좋게 빗나갔다.
실제 순서는 SELECT -> INSERT -> SELECT 순이다.
이 이유는 Hibernate 공식 가이드에서 찾아볼 수 있다.
Hibernate ORM 6.2.6.Final User Guide
Fetching, essentially, is the process of grabbing data from the database and making it available to the application. Tuning how an application does fetching is one of the biggest factors in determining how an application will perform. Fetching too much dat
docs.jboss.org
AUTO flush circumstances:
1. prior to committing a Transaction
2. prior to executing a JPQL/HQL query that overlaps with the queued entity actions
3. before executing any native SQL query that has no registered synchronization
2번에 주목 해야한다.
JPQL 직전 이기는 하지만 조건이 붙어있다. 대기중인 엔티티 작업이 겹쳐있을 때 AUTO flush를 수행한다.
@Query 는 PC(영속성 컨텍스트)를 거치지않고 DB에 직접 질의하며, 호출 직전 Flush 하는 줄 알았지만 위 조건을 만족시켜야 Flush 한다.
혹시나 persist()만 적용 되는건 아닌가? 라는 의심병이 도졌다.
update 쿼리도 마찬가지로 순서가 SELECT -> UPDATE -> SELECT 순서다.
위 주제를 알아보며 문득 또 호기심이 생겨났다.
Query Method 방식으로 생성한 메서드 (메서드 이름을 기반으로 JPQL을 만들어주는 기술) 는 저 기준에 똑같이 부합할까?
공식문서에서 근거를 찾았기때문에 확신했다. 당연히 그럴 것이라고.
Query Method도 우릴 편하게 JPQL을 생성해줄 뿐이지 JPQL인것은 변함이 없다.
직접 확인해보자.
현재 UMC 4기에서 진행중인 프로젝트다. (코드가 좀 더럽다)
필자는 댓글 구현 부분을 담당하고있고 위 로직은 댓글을 삭제하는 로직이다.
간단히 순서를 나타내자면 자식댓글 삭제 -> 해당 댓글의 부모댓글의 자식댓글이 없고 부모댓글이 삭제상태인지 확인 -> 참이라면 부모댓글 삭제
commentRepository : deleteById(기본 제공 메서드) , existsByParentCommentId (쿼리메서드 방식으로 생성)
deleteById -> exstsByParentCommentId -> deleteById 로 로직을 탄다면 아래와 같아야한다.
- 첫 번째 delete 쿼리가 SQL 저장소에 저장
- existsByParentCommentId 의 select 쿼리는 SQL 저장소에 겹치는 엔티티 작업이 있기때문에 Flush
- 두 번째 delete 쿼리가 commit 시점에 질의
DELETE -> SELECT -> DELETE 로 쿼리가 예상한대로 잘 나갔다!
결론
@Query를 붙인 커스텀 메서드라고해서 무조건 호출 직전에 Flush를 하는건 아니다.
@Query 뿐만이 아니라 Hibernate가 생성한 JPQL 이라면
영속성컨텍스트의 SQL 저장소에 겹치는 엔티티 작업이 있다면 먼저 Flush 후 DB에 직접 질의한다.
'Spring' 카테고리의 다른 글
[Spring Security JWT 로그인 (2)] JWT가 탈취된다면 어떻게 대응해야 할까 (0) | 2024.03.10 |
---|---|
Redis Session Clustering [세션 고정] (0) | 2023.12.17 |
S3를 이용한 사용자의 고아 이미지 처리 (1) | 2023.12.02 |
코드의 중복과 Null 처리 (0) | 2023.09.25 |
Cannot delete or update a parent row: a foreign key constraint fails [CASCADE Option, OrphanRemoval, @Modifying, JPQL 에 대하여] (0) | 2023.07.18 |