Programming/Spring,JPA

[JPA/Hibernate] Flush 차이

우니wooni 2024. 11. 22. 18:47

Flush

JPA와 Hibenate의 flush 동작은 개념적으로 동일하지만, 구현의 세부 사항에서 차이가 있다.

 

JPA flush

JPA는 표준 사양으로 구현체가 다양한데 Hibernate가 그 중 하나이다. JPA의 flush 는 엔티티 매니저를 통해 수행되며 아래와 같은 경우에 호출된다.

  • 트랜잭션이 커밋될 때
  • JPQL 쿼리 실행 전
  • 명시적으로 flush 호출

 

Hibernate flush

Hibernate는 JPA 구현체 중 하나로, JPA 사양을 따르면서도 자체적으로 flush 실행 시점을 좀 더 세밀하게 제어한다. Hibernate에서 flush가 호출 되는 경우는 아래와 같다.

  • 트랜잭션을 커밋하기 전에 트리거 된다.
  • JPQL 쿼리 결과가 영속성 컨텍스트의 변경 사항에 영향을 받을 수 있을 때, 쿼리를 실행하기 전 트리거 된다.
  • flush()를 호출할 때

 

JPQL 쿼리 결과가 영속성 컨텍스트의 변경 사항에 영향을 받을 수 있을 때, 쿼리를 실행하기 전 트리거 된다.

 

해당 내용에 대해 더 자세히 살펴보자. 아래 코드에서는 트랜잭션이 커밋되기 직전 flush가 발생한다.

session.getTransaction().begin();

Author author = new Author();
session.persist(author);

var books =
	// new Author 엔티티는 Books 관련 쿼리에 어떠한 영향도 미치지 않는다.
    session.createSelectionQuery("from Book")
    // flush 할 필요 없음
    .getResultList();

// flush는 커밋 되기 전 이 지점에서 발생한다.
session.getTransaction().commit();

 

그러나 이 코드에서는 쿼리가 실행되기 전 flush가 발생한다.

session.getTransaction().begin();

Book book = new Book();
session.persist(book);

var books =
        // new Book은 Books 관련 쿼리에 영향을 미친다.
        session.createSelectionQuery("from Book")
        // flush가 발생하는 지점(쿼리가 실행되기 전)
        .getResultList();

// 변경 사항은 데이터베이스에 이미 flush 되어서 이 지점에서는 flush 할 내용이 없다.
session.getTransaction().commit();
session.getTransaction().begin();

Author author = new Author();
session.persist(author);

var books = session.createSelectionQuery("from Book")
	.getResultList();
							
var authors = session.createSelectionQuery("from Author")
	// flush가 발생하는 지점
    .getResultList();

session.getTransaction().commit();

 

결론적으로 Hibernate는 수행하려는 JPQL 쿼리가 영속성 컨텍스트에 대기중인 엔티티와 겹치면 쿼리를 실행하기 전 Flush한다.

JPA는 기본 Flush Mode가 Auto이지만, 구현체로 Hibernate를 사용할 경우 JPQL 쿼리를 실행할 때마다 Flush를 자동 호출하지 않는 것이다.


FlushMode 설정

FlushMode 설정은 JPA와 하이버네이트에서 flush 동작을 제어하는 데 사용한다. 이 설정을 통해 데이터베이스 변경 사항을 동기화하는 시점을 조정할 수 있다.

 

 

JPA FlushModeType

✔️ FlushModeType.AUTO

쿼리를 실행하기 전, 또는 트랜잭션이 커밋될 때 flush가 자동으로 발생한다.

 

✔️ FlushModeType.COMMIT

트랜잭션이 커밋될 때만 flush 발생한다.

 

 

Hibernate FlushMode 유형

✔️ AUTO(기본 설정)

이 모드에서는 Hibernate가 자동으로 flush를 결정한다. 트랜잭션 커밋 전에, 또는 쿼리 실행 전에 영속성 컨텍스트에 변경된 데이터가 있을 경우 자동으로 flush가 발생한다. 쿼리 실행 시 결과가 영속성 컨텍스트의 변경 사항에 영향을 받을 가능성이 있으면 flush 발생한다.

 

✔️ COMMIT

트랜잭션이 커밋될 때만 flush가 발생한다. 쿼리 실행 전에는 flush가 발생하지 않기 때문에, 쿼리 결과가 영속성 컨텍스트의 변경 사항에 영향을 받지 않는다. 일부 성능 최적화가 가능하겠지만 예상치 못한 쿼리 결과를 초래할 수 있다.

 

✔️ ALWAYS

각 쿼리 실행 전마다 flush가 발생한다.

 

✔️ MANUAL

개발자가 직접 flush를 호출해야만 한다.