JPA-시작하기 에서 어느 정도 영속성 컨텍스트와 엔티티의 생명주기를 간단하게 알아봤다. 이 영속성 컨텍스트의 특징을 좀 더 자세히 알아보도록 하자.

플러시

플러시는 영속성 컨텍스트의 변경 내용을 데이터베이스에 반영한다. 이 때 영속성 컨텍스트에 보관된 엔티티를 지우는 것은 아니다. 영속성 컨텍스트의 변경 내용을 데이터베이스에 동기화 하는 것이다.

플러시 과정

  1. 변경 감지가 동작해서 영속성 컨텍스트에 있는 모든 엔티티를 스냅샷과 비교하여 수정된 엔티티를 찾는다.
  2. 수정된 엔티티는 수정 쿼리를 만들어서 쓰기 지연 SQL 저장소에 등록한다.
  3. 쓰기 지연 SQL 저장소의 쿼리를 데이터베이스에 전송한다.

플러시 방법

  • em.flush()를 직접 호출한다. 테스트나 다른 프레임워크와 JPA를 함께 사용할 때를 제외하고는 거의 사용하지 않는다.
  • 트랜잭션 커밋 시 플러시가 자동 호출된다.
  • JPQL 쿼리 실행 시 플러시가 자동 호출된다. JPQL을 실행하면 JPQL이 SQL로 변환되어 데이터베이스에서 엔티티를 조회한다. SQL 쿼리를 실행하기 위해서는 영속성 컨텍스트를 플러시해서 변경 내용을 데이터베이스에 반영해야 하기 때문에 플러시가 발생한다.

플러시 모드 옵션

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

준영속

영속성 컨텍스트가 관리하는 영속 상태의 엔티티가 영속성 컨텍스트에서 분리된 것을 준영속 상태라고 한다. 준영속 상태의 엔티티는 영속성 컨텍스트가 제공하는 기능을 사용할 수 없다.

준영속 상태로 만드는 방법

아래와 같은 3가지 방법이 있다. 참고로 영속 상태의 엔티티가 준영속 상태로 변할 때 1차 캐시와 관련된 쓰기 지연 SQL 저장소 관련 SQL이 제거되고 데이터 베이스에 플러시가 발생하지는 않는다.

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

병합: merge()

준영속 상태의 엔티티를 다시 영속 상태로 변경하려면 사용할 수 있는 메소드다.

Member mergeMember = em2.merge(member);

위 코드를 호출하면 mergeMember는 영속 상태가 된고 member는 여전히 준영속 상태이다. 위 메소드를 호출하면 영속 컨텍스트와 DB를 통해 동일한 id를 가진 엔티티를 찾은 후 업데이트 시킨다. 해당 id가 존재하지 않을 경우 새로운 영속 상태의 엔티티를 만들어준다.

참고 자료

자바 ORM 표준 JPA 프로그래밍 (김영한) https://stackoverflow.com/questions/1069992/jpa-entitymanager-why-use-persist-over-merge

댓글남기기