본문 바로가기
JPA

[JPA] 플러시(Flush)

by snow_white 2022. 7. 18.
※ 인프런 강의 김영한님의 「자바 ORM 표준 JPA 프로그래밍」을 학습한 내용을 정리한 글입니다. 

 

플러시 (Flush) ❓

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


플러시의 발생

  • 변경 감지 (Dirty Checking)
  • 수정된 Entity를 쓰기 지연 SQL 저장소에 등록
  • 쓰기 지연 SQL 저장소의 Query를 DB에 전송한 (등록, 수정, 삭제 Query)

flish가 발생한다고 해서 commit이 이루어지는 것이 아니고 flush 다음에 실제 commit이 일어난다.
플러시가 동작할 수 있는 이유는 데이터베이스 트랜잭션(작업 단위)이라는 개념이 있기 때문이다.
트랜잭션이 시작되고 해당 트랜잭션이 commit 되는 시점 직전에만 동기화 (변경 내용을 날림) 해주면 되기 때문에, 그 사이에서 플러시 매커니즘의 동작이 가능한 것이다.


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

1. em.flush() - 직접 호출

// 영속 상태 (Persistence Context 에 의해 Entity 가 관리되는 상태)
Member member = new Member(200L, "A");
entityManager.persist(member); // 영속성 컨텍스트에 담기고 쿼리가 저장소에 담겨 있음!

entityManager.flush(); // 강제 호출 (쿼리가 DB 에 반영됨)
// DB INSERT Query 출력됨
System.out.println("Transaction commit 됨.");
tx.commit(); // DB에 insert query 가 반영됨


❓ 플러시가 일어나면 1차 캐시가 모두 지워질까?
✅ 아님! 그대로 남아있다.
영속성 컨텍스트 내부의 쓰기 지연 SQL 저장소에 있는 Query들만 DB에 반영이 되는 과정일 뿐이다.

 

2. 트랜잭션 커밋 - 플러시 자동 호출

 

3. JPQL 쿼리 실행 - 플러시 자동 호출

em.persist(memberA);
em.persist(memberB);
em.persist(memberC);

// 중간에 JPQL 실행
query = entityManager.createQuery("select m from Member m", Member.class);
List<Member> members = query.getResultList();

memberA, B, C 를 영속성 컨텍스트에 저장한 상태에서 DB에서 바로 조회가 될까?
✅ 조회가 되지 않는다.
DB 에 Query로도 날라가야 반영이 될텐데 INSERT Query 자체가 날라가지 않은 상태이다. 이런 상태에서 JPQL로 DB에서 가져오는 SELECT Query 요청을 한 것이므로 당연히 조회되지 않는다.
JPQL은 SQL로 번역이 돼서 실행되는 것이다. 따라서 A, B, C에 대한 존재를 가져올 수가 없다.
이를 방지하기 위하여 JPA의 기본 모드는 JPQL 쿼리 실행 시 flush()를 자동으로 날린다.
즉, JPQL 쿼리 실행 시 플러시 자동 호출로 인해 위의 코드는 조회가 가능하다.

 

플러시 모드 옵션

em.setFlushMode(FlushModeType.COMMIT);
  • FlushModeType.AUTO : 커밋이나 쿼리를 실행할 때 플러시 (기본값)
    • Transaction 을 commit 하거나 Query를 실행할 때 flush()를 먼저 수행하고 commit 한다.
  • FlushModeType.COMMIT : Transaction commit 할때만 플러시
    • Transaction commit 할때만 flush()를 먼저 수행한다.
      Query를 실행할 때는 flush()를 먼저 수행하지 않는다.
    • 이점: persist 한 것과 전혀 다른 테이블을 조회하는 경우

🔅 그래서 플러시는..

  • 영속성 컨텍스트를 비우지 않음 (이름 때문에 오해하지 말자!)
  • 영속성 컨텍스트의 변경 내용을 데이터베이스에 동기화
  • 트랜잭션이라는 작업 단위가 중요 → 커밋 직전에만 동기화하면 됨

'JPA' 카테고리의 다른 글

[JPA] 연관관계 매핑 - 단방향 연관관계  (0) 2022.08.07
[JPA] 엔티티 매핑  (0) 2022.07.28
[JPA] 준영속 상태  (0) 2022.07.18
[JPA] 영속성 관리  (0) 2022.07.18
[JPA] JPA의 소개  (0) 2022.07.17

댓글