본문 바로가기

카테고리 없음

[JPA] flush란

flush()란?

영속성 컨텍스트의 변경 내용을 디비에 반영하는 것이다.
(즉, 영속 컨텍스트 안에 있는 쓰기 지연 SQL 저장소의 쿼리들을 디비에 보내는 것이다.)
보통 트랜젝션이 커밋할 때, flush가 일어난다.


flush가 발생하면 무슨 일이 일어나는가?

  • 변경 감지(더티 체킹) - 1차 캐시의 스냅샷과 현재 Entity 체킹하는 것.

수정된 엔티티 쓰기 지연 SQL 저장소에 등록

  • 쓰기 지연 SQL 저장소의 쿼리를 디비에 전송

(어찌 보면 위 3가지는 Entity를 조회한 후, 수정하고 커밋하는 과정을 단계별로 나열한 것과 같다.)

영속성 컨텍스트를 플러시하는 방법

  • em.flush() - 직접 호출
  • 트랜잭션 커밋 - 플러시 자동 호출
  • JPQL 쿼리 실행 - 플러시 자동 호출

em.flush()직접 호출

위 예시는 em.flush()를 통해 플러시를 직접 호출한 것이다.
원래 커밋 시점에 flush()가 되어 쿼리문이 디비에 날라가지만, 앞에서 이미 flush()를 통해 보냈기 떄문에
밑에 commit시점에는 날릴 쿼리문이 없는 상태일 것이다. 이렇게 직접 호출하는 방법이 있구나 하고 넘기면 된다.

JPQL 쿼리 실행할 때도 flush()가 자동 호출이 만들어진 이유

JPQL인 em.createQuery를 통해 실행했으면, 위에 영속 컨텍스트에 저장한 member A, B, C를 조회할 수는 없다.(어찌보면 당연한 말이다.)
그래서 이런 상황들을 방지하고자, JPQL을 실행할 떄, 무조건 flush를 날려버린다.


플러시 모드 옵션

기본적으로 AUTO로 설정되어 있다. 커밋이나 쿼리를 실행할 때, flush()가 실행되게 한다.

COMMIT 설정을 통해 커밋할 때만 플러시를 실행할 수 있지만, 아마 거의 사용할 일이 없을 것이다.
그냥 이런게 있구나 정도로 봐도 될 것 같다.

그래서 플러시는!

  • 영속성 컨텍스트를 비우지 않는다. (혹시라도 헷갈리지 말자. SQL 저장소의 쿼리문을 디비에 보내는 것이지, 절대 영속성 컨텍스트를 비우지 않고, 당연히 1차 캐시 또한 비우지 않는다.)
  • 영속성 컨텍스트의 변경내용을 디비에 동기화(더티 체킹도 이와 같은 현상 중 하나로 볼 수 있다.)
  • 트랜잭션이라는 작업 단위가 중요 -> 커밋 직전에만 동기화 하면 된다.