Study/Java&Spring

JPA Flush(플러시)

kdhoooon 2022. 1. 17. 15:27

플러시란?

  • 영속성 컨텍스트의 변경 내용을 DB에 반영하는 것을 말함
  • Transaction commit 이 일어날 때 flush가 동작하는데, 이때 쓰기 지연 저장소에 쌓아 놨던 INSERT, UPDATE, DELETE SQL 들이 DB에 날라간다.
    • 영속성 컨텍스트를 비우는 것이 아니다.
  • 쉽게 얘기해서 영속성 컨텍스트의 변경 사항들과 DB의 상태를 맞추는 작업이다.
    • 플러시는 영속성 컨텍스트의 변경 내용을 DB에 동기화 한다.

 

동작 과정

  1. 변경 감지(Dirty Checking)
  2. 수정된 Entity를 쓰기 지연 SQL 저장소에 등록한다.
  3. 쓰기 지연 SQL 저장소의 Query를 DB에 전송 ( create, update, delete Query)
    • flush가 발생한다고 해서 commit이 이루어지는 것이 아니고 flush 다음에 실제 commit이 일어난다.
    • 플러시가 동작할 수 있는 이유는 데이터베이스 트랜잭션(작업 단위)이라는 개념이 있기 때문
      • 트랜잭션이 시작되고 해당 트랜잭션이 commit 되는 시점 직전에만 동기화(변경 내용을 날림) 해주면 되기 때문에, 그 사이에서 플러시 매커니즘이 동작이 가능한 것
    • JPA는 기본적으로 데이터를 맞추거나 동시성에 관련된 것을은 데이터베이스 트랜잭션에 위임한다.

 

사용 방법

  1. EntityManager.flush() 을 통한 직접 호출
    • Member member = new Member(1L, "test");
      entityManger.persist(member);
      
      entityManger.fulsh() // 강제 호출 쿼리가 DB에 반영
      transaciton.commit();
       
    • 플러시(flush)가 일어나도 1차 캐시가 남아있다.(쓰기 지연 SQL 저장소에 있는 Query들만 DB에 전송까지만 되는 과정일 뿐이다.)
  2. 트랜잭션 커밋 시 플러시 자동 호출
  3. JPQL 쿼리 실행 시 플러시 자동 호출
    • entityManger.persist(member1);
      entityManger.persist(member2);
      entityManger.persist(member3);
      
      query = entityManger.createQuery("select m from Member m", Member.class);
      List<Member> members = query.getResultList();
    • member 1, 2, 3 을 영속성컨텍스트에 저장한 상태에서 바로 조회하면 조회가 되지않는다.
      • DB에 Query로도 날라가야 반영이 될텐데 INSERT Query 자체가 날라가지 않은 상태다.
      • 이런 상태에서 JPQL로 DB에서 가져오는 SELECT Query 요청을 한 것이므로 당연히 조회되지 않는다.
      • JPQL은 SQL로 번역이 돼서 실행되는 것이다.
    • 이 때문에 JPA의 기본 모드는 JPQL 쿼리 실행시 flush()를 자동으로 날린다.
      • 즉, JPQL 쿼리 실행 시 플러시 자동 호출로 인해 위의 코드는 조회가 가능하다.

 

옵션(EntityManager.setFlushMode())

  • FlushModeType.COMMIT
    • Transaction commit 할 때만 flush()를 먼저 수행한다.
    • Query를 실행할 때는 flush()를 먼저 수행하지 않는다.
    • 장점 : persist한 것과 전혀 다른 테이블을 조회하는 경우
  • FlushModeType.AUTO
    • 기본 설정 값
    • Transaciton을 commit 하거나 Query를 실행할 때 flush()를 먼저 수행한다.