나를 기록하다
article thumbnail
Published 2023. 3. 19. 12:01
[JPA] Flush Java/JPA
반응형

Flush란?

JPA에서 "flush"는

엔티티 매니저의 컨텍스트에 대한 변경 사항을 기존의 데이터베이스와 동기화하는 프로세스

를 말합니다.

엔티티 매니저에서 관리되는 엔티티에 대한 작업을 수행할 때(예: persist, remove, update 등),

변경 사항은 즉시 데이터베이스에 유지되지 않습니다. 대신, 변경 사항은 엔티티 매니저의 컨텍스트에 보관되어 플러시 작업이 트리거될 때까지 유지

됩니다.

그 시점에서 변경 사항이 데이터베이스로 전송되어 커밋

됩니다.

플러시 작업을 수동으로 트리거하려는 경우 몇 가지 시나리오가 있습니다.

  • 관리되는 엔티티에 대한 변경 사항이 즉시 데이터베이스에 유지되도록 보장하기 위해서입니다.
  • 플러시 작업 이후에 실행되는 모든 SQL 쿼리에서 데이터베이스에서 최신 데이터를 반환하도록 보장하기 위해서입니다.
  • 플러시 작업으로 인해 발생할 수 있는 모든 지속성 예외를 잡기 위해서입니다.

엔티티 매니저에서 flush() 메서드를 사용하여 플러시 작업을 호출할 수 있습니다.

 

 

 

Flush의 기능

JPA에서 flush는 엔티티 매니저에서 관리되는 엔티티의 변경 사항을 데이터베이스에 동기화하는 작업입니다.

엔티티 매니저에서 관리되는 엔티티에 대한 변경 사항을 수행하면, 엔티티 매니저는 이를 일시적으로 캐시에 보관합니다. 그리고 나중에 트랜잭션이 커밋될 때 이 변경 사항들이 일괄적으로 데이터베이스에 반영됩니다. 하지만 때로는 이 변경 사항을 즉시 반영하고 싶을 때가 있습니다. 이런 경우에 flush를 사용합니다.

flush의 주요 기능은 다음과 같습니다.

  1. 변경 사항을 즉시 반영합니다. (변경 감지)

flush를 호출하면 엔티티 매니저가 캐시에 보관된 변경 사항을 데이터베이스에 즉시 반영합니다. 이를 통해 변경 사항을 즉시 확인할 수 있습니다.

  1. 쓰기 지연 방식을 사용하여 효율적으로 변경 사항을 반영합니다.

flush는 엔티티 매니저가 변경 사항을 즉시 데이터베이스에 반영하지만, 이를 위해 매번 SQL 쿼리를 실행하지 않습니다. 대신, 쓰기 지연 방식을 사용하여 여러 변경 사항을 효율적으로 일괄 처리합니다.

  1. 트랜잭션 범위 내에서 변경 사항을 보장합니다.

flush는 트랜잭션 범위 내에서 동작합니다. 즉, flush를 호출하기 전에 시작된 트랜잭션이 커밋되기 전까지 변경 사항은 데이터베이스에 적용되지 않습니다. 이를 통해 데이터 일관성을 보장할 수 있습니다.

  1. 예외 처리를 수행합니다.

flush 작업을 수행하는 동안 예외가 발생할 수 있습니다. flush는 이러한 예외를 처리하고 적절한 예외를 던집니다. 이를 통해 문제를 빠르게 파악하고 해결할 수 있습니다.

 

 

 

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

JPA에서 영속성 컨텍스트를 flush하는 방법은 간단합니다.

엔티티 매니저에서 flush() 메서드를 호출하면 현재 영속성 컨텍스트에 보관된 엔티티의 변경 사항이 데이터베이스에 즉시 반영됩니다.

예를 들어, 다음은 EntityManager를 사용하여 flush하는 예제입니다.

EntityManager em = entityManagerFactory.createEntityManager(); em.getTransaction().begin();  // 영속성 컨텍스트에 변경 사항을 수행한다. // ...  // 변경 사항을 데이터베이스에 즉시 반영한다. em.flush();  em.getTransaction().commit(); em.close();  

위 코드에서 em.flush() 메서드를 호출하면, 변경 사항이 데이터베이스에 즉시 반영됩니다.

flush 작업은 쓰기 지연 방식을 사용하여 효율적으로 수행되므로, flush를 호출하더라도 매번 SQL 쿼리가 실행되지는 않습니다. 대신, 엔티티 매니저가 적절한 시점에서 적절한 쿼리를 실행하여 변경 사항을 일괄 처리합니다.

참고로, flush 작업은 영속성 컨텍스트 범위 내에서 수행되므로, flush를 호출하기 전에 시작된 트랜잭션이 커밋되기 전까지 변경 사항은 데이터베이스에 적용되지 않습니다. 따라서, flush 작업은 트랜잭션 범위 내에서 사용하는 것이 일반적입니다.

 

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

 

 

 

JPQL 쿼리 실행 시 플러시가 자동으로 호출되는 이유

JPQL(Java Persistence Query Language) 쿼리 실행 시 flush가 자동으로 호출되는 이유는 JPA에서 지연 로딩(lazy loading)을 지원하기 위함입니다.

JPA에서는 기본적으로 지연 로딩 방식을 사용하여 엔티티를 로딩합니다. 이 방식은 필요한 시점에 데이터베이스에서 엔티티를 로딩하여 메모리 사용량을 최적화하고, 성능을 향상시킬 수 있습니다.

하지만 지연 로딩 방식에서는 데이터베이스에서 로딩되지 않은 엔티티의 필드에 접근하는 경우 LazyInitializationException이 발생합니다. 이 때, 엔티티 매니저는 해당 엔티티를 영속성 컨텍스트에 등록하고, 필요한 데이터를 데이터베이스에서 로딩합니다.

JPQL 쿼리 실행 시, 해당 쿼리에서 사용하는 엔티티 중에서 영속성 컨텍스트에 등록되지 않은 엔티티가 있을 경우, 엔티티 매니저는 이를 자동으로 영속성 컨텍스트에 등록합니다. 이 때, 영속성 컨텍스트에 등록된 엔티티와 데이터베이스의 상태가 다를 수 있으므로, 자동으로 flush가 호출되어 변경 사항을 데이터베이스에 반영합니다.

이를 통해 JPQL 쿼리 실행 시, 영속성 컨텍스트와 데이터베이스의 일관성을 유지할 수 있습니다.

만약 이러한 자동 flush 기능을 원하지 않는다면, Query.setFlushMode(FlushModeType.COMMIT) 메서드를 사용하여 flush 모드를 COMMIT으로 설정하면 됩니다. 이를 설정하면 JPQL 쿼리 실행 시, 자동으로 flush가 호출되지 않고, 트랜잭션이 커밋될 때 일괄적으로 변경 사항이 데이터베이스에 반영됩니다.

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

 

 

 

플러시 모드 옵션

em.setFlushMode(FlushModeType.AUTO) // 커밋이나 쿼리를 실행할 때 플러시(기본값) em.setFlushMode(FlushModeType.COMMIT) // 커밋할 때만 플러시

 

 

 

준영속 상태

JPA에서 엔티티는 다음 세 가지 상태 중 하나를 가지게 됩니다.

  1. 영속 상태(Persistent): 영속성 컨텍스트에 저장된 상태입니다. 영속성 컨텍스트는 엔티티의 생명주기를 관리하며, 엔티티가 영속성 컨텍스트에 저장되면 해당 엔티티는 영속 상태가 됩니다.
  1. 트랜잭션 범위 밖의 상태(Detached): 영속성 컨텍스트와는 무관한 상태입니다. 즉, 영속성 컨텍스트에서 분리된 상태이며, 해당 엔티티의 변경 사항은 데이터베이스에 반영되지 않습니다.
  1. 새로운 상태(New or Transient): 영속성 컨텍스트와 관계없는 상태입니다. 즉, 데이터베이스에 저장되지 않은 새로운 엔티티입니다.

준영속 상태(Detached)는 영속성 컨텍스트에서 분리된 상태로, 영속 상태에서 분리되어 영속성 컨텍스트와는 더 이상 관계가 없는 상태입니다. 이 상태에서는 엔티티를 데이터베이스에 저장할 수 없으며, 데이터베이스에서 엔티티를 삭제할 수도 없습니다.

준영속 상태로 전환하는 방법은 다음과 같습니다.

  1. 엔티티 매니저의 detach() 메서드를 호출하여 해당 엔티티를 분리합니다.
  1. 트랜잭션이 종료되면, 영속성 컨텍스트에 저장된 모든 엔티티가 자동으로 준영속 상태가 됩니다.

준영속 상태의 엔티티는 다시 영속 상태로 만들 수 있습니다. 이 때, EntityManager.merge() 메서드를 호출하면 준영속 상태의 엔티티를 영속 상태로 만들 수 있습니다. 이 때, merge 메서드는 준영속 상태의 엔티티를 복사하여 새로운 영속 상태의 엔티티를 만드는데, 데이터베이스의 상태와 일치하도록 복사됩니다.

 

  • em.detach(entity) : 특정 엔티티만 준영속 상태로 전환
  • em.clear() : 영속성 컨텍스트를 완전히 초기화
  • em.close() : 영속성 컨텍스트를 종료

Uploaded by

N2T
반응형

'Java > JPA' 카테고리의 다른 글

[JPA] Getter and Setter  (0) 2023.04.02
[JPA] 객체와 테이블, 조인 전략  (0) 2023.04.02
[JPA] JPQL의 기초  (0) 2023.03.16
[JPA] JPA 기초설정과 H2 DB 연동  (0) 2023.03.16
[JPA] JPA 용어 및 개요  (0) 2023.03.15
profile

나를 기록하다

@prao

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!

profile on loading

Loading...