🌱 SPRING/JPA

[JPA] 플러시(flush)

1HOON 2020. 6. 13. 15:32

 

플러시(flush)란?

영속성 컨텍스트의 변경 내용을 데이터베이스에 반영하는 것을 의미한다.

아래 경우에 flush가 발생한다.

 

  • 트랜잭션에 commit이 발생할 때
  • EntityManager의 flush 메서드를 호출했을 때
  • JPQL 쿼리가 실행될 때

 

그리고 flush가 발생하면 쓰기 지연 저장소에 저장된 SQL(INSERT/UPDATE/DELETE)이 데이터베이스로 전송된다.

IO 처리 시 FileStream.flush() 메서드를 사용하는 경험이 있어 flush 발생 시 영속성 컨텍스트가 비워지는 것이 아닌지 헷갈릴 수 있으나, 아니다. flush가 발생한다고 해서 영속성 컨텍스트가 비워지는 것이 아니고, 변경 사항을 DB와 동기화 하는 것을 의미한다. 그러한 이유로 flush가 발생해도 1차 캐시는 유지된다.

 

위 세가지 경우에서 JPQL 쿼리가 실행될 때 flush가 발생하는 이유는 무엇일까? 아래 코드를 보자.

em.persist(memberA); // 영속성 컨텍스트에 memberA가 추가됨
em.persist(memberB); // 영속성 컨텍스트에 memberB가 추가됨
em.persist(memberC); // 영속성 컨텍스트에 memberC가 추가됨

// JPQL 실행
query = em.createQuery("select m from Member m", Member.class);

List<Member> members= query.getResultList(); // ???

em.persist 메서드 수행 시 각각의 Member 객체가 영속성 컨텍스트에 추가되어 영속 상태가 되는데, 그 이후 JPQL로 전체 Member 목록을 조회하도록 하고 있다.

 

이때, 만약 JPQL 수행 시 flush가 발생하지 않는다면 어떻게 될까? JQPL로 조회한 members 리스트에는 위에서 추가한 memberA, memberB, memberC가 포함되지 않는 문제가 생긴다. JPA에서는 이러한 문제를 예방하기 위해 JPQL 수행 전 자동으로 flush를 발생시켜 DB와 영속성 컨텍스트간의 동기화를 수행하도록 하고 있다.

때문에, members 리스트에는 memberA, memberB, memberC가 포함되어 조회되는 것이다.

 

 

플러시 동작 과정

  1. 영속성 컨텍스트에서 변경을 감지한다. → Dirty Checking
  2. 수정이 발생한 Entity를 지연 SQL 저장소에 등록한다.
  3. 쓰기 지연 SQL 저장소의 쿼리를 데이터베이스로 전송한다.

주의할 점은, 데이터베이스에는 트랜잭션이라는 작업 단위가 존재하기 때문에 한 트랜잭션 내에서 flush가 아무리 발생해도 DB commit은 발생하지 않는다는 점이다. DB commit은 해당 트랜잭션이 commit 될 때 발생한다.

 

 

플러시 모드 옵션

  • FlushModeType.AUTO : 커밋이나 쿼리를 실행할 때 플러시 (default)
  • FlushModeType.COMMIT : 커밋할 때만 플러시

 

 


출처 :: 인프런 강의(자바 ORM 표준 JPA 프로그래밍 - 기본편)

반응형