Spring/JPA

[Spring/JPA] 엔티티의 생명주기

오잎 클로버 2023. 2. 16. 11:07
728x90

엔티티 상태

JPA Entity 에는 다음과 같은 4가지 종류의 상태가 존재한다.

비영속 (new/transient) 영속성 컨텍스트와 전혀 관게가 없는 상태
영속 (managed) 영속성 컨텍스트에 저장된 상태 (관리되는 상태)
준영속 (detached) 영속성 컨텍스트에 저장되었다가 분리된 상태
 삭제 (removed) 삭제된 상태

생명주기는 다음 그림과 같다.

출처: https://ultrakain.gitbooks.io/jpa/content/chapter3/chapter3.3.html

 

비영속

  • 순수한 객체 상태이며, 아직 영속성 컨텍스트에 저장되지 않은 상태이다.
  • 영속성 컨테스트나 데이터베이스와 상관없는 상태이다.
// 객체를 생성한 상태 (비영속)
Member member = new Member();
member.setUsername("clover");

EntityManager#persist 를 호출하기 전 상태이다.

 

영속

  • EntityManager 를 통해 엔티티를 영속성 컨텍스트에 저장한 상태이다.
  • 영속성 컨텍스트에 의해 관리되는 엔티티이다.
  • EntityManager 혹은 JPQL의 데이터베이스 접근을 통해 생성/조회된 엔티티들이 영속 상태이다.
// 객체를 저장한 상태 (영속)
entityManager.persist(member);

EntityManager#persist 를 호출 후 상태이다.

 

flush

flush 는 영속성 컨텍스트의 변경 내용을 데이터베이스에 반영하는 행위

flush 실행

  1. 변경 감지 동작. 모든 엔티티를 스냅샷과 비교한다.
  2. 수정된 엔티티는 수정 쿼리를 만들어 쓰기 지연 SQL 저장소 등록
  3. 쓰기 지연 SQL 저장소의 쿼리를 데이터베이스에 전송 - 등록, 수정, 삭제 쿼리

영속성 컨텍스트를 flush 하는 방법들

  1. EntityManager#flush 를 직접 호출 - 테스트나 다른 프레임워크와 함께 사용할 때를 제외하고 잘 사용되지 않음
  2. 트랜잭션 커밋 시 flush 가 자동 호출 - JPA 트랜잭션 커밋 시 자동 호출이 default 값이다.
  3. JPQL (Java Persistence Query Language) 쿼리 실행 시 자동 호출 - flush 하기 중간에 조회/삭제 등이 발생할 수 있기에 JPQL 실행 시, 플러시가 자동으로 호출된다.

flush 모드 옵션

  • 별도로 설정하지 않으면 AUTO 동작.
  • 대부분 AUTO 기본 설정을 그대로 사용.
모드 설명
FlushMode.AUTO 커밋이나 쿼리를 실행할 때 플러시 (default)
FlushMode.COMMIT 커밋할 때만 플러시
플러시는 영속성 컨텍스트의 변경 내용을 데이터베이스에 동기화.
영속성 컨텍스트에 보관된 엔티티를 지우는 것이 아님.

 

준영속

  • 영속성 컨텍스트가 관리하던 영속 상태의 엔티티를 영속성 컨텍스트에서 더 이상 관리하지 않는 상태이다.
  • EntityManager#detach 를 통한 명시적 호출로 준영속화가 가능하다.
  • EntityManager#close 를 통해 영속성 컨텍스트를 닫으므로서 준영속화가 가능하다.
  • EntityManager#clear 를 통해 영속성 컨텍스트를 초기화하여 준영속화가 가능하다.
entityManager.detach(member);

detach 메소드를 명시적 호출할 경우, 해당 엔티티를 더 이상 관리하지 말라고 하는 것이므로, 1차 캐시부터 쓰기 지연           SQL 저장소까지 해당 엔티티를 관리하기 위한 모든 정보가 삭제된다.

clear 메소드를 호출하여, 영속성 컨텍스트를 초기화해서 영속성 컨텍스트의 모든 엔티티를 준영속 상태로 만들 수 있다.

※ 준영속 상태로 진입하기 위해 해당 엔티티들의 모든 정보(1차 캐시, 쓰기 지연 SQL 저장소 등)를 전부 삭제한다.

close 메소드를 호출하여, 해당 영속성 컨텍스트가 관리하던 영속 상태의 엔티티가 모두 준영속 상태가 된다.

 

준영속은 비영속 상태에 가깝다. 1차 캐시, 쓰기 지연, 변경 감지, 지연 로딩을 포함한 영속성 컨텍스트가 지원하는
  어떤 기능도 동작하지 않는다. 하지만, 이미 한 번 영속 상태였으므로 반드시 식별자 값을 가지고 있다.

지연 로딩: 실제 객체 대신 프록시 객체를 로딩해 두고 해당 객체를 실제 사용할 때 영속성 컨텍스트를 통해
    데이터를 불러오는 방법

 

merge

  • 준영속 상태의 엔티티를 다시 영속 상태로 변경하려면 병합(merge)를 사용하면 된다.
  • merge() 메소드는 준영속 상태의 엔티티를 받아서 그 정보로 새로운 영속 상태의 엔티티를 반환.

만일 영속상태가 해제된, 즉 준영속 상태의 엔티티를 merge 를 한다면 다음과 같이 작동하여 다시 영속상태가 된다.

  1. merge()를 실행한다.
  2. 파라미터로 넘어온 준영속 엔티티의 식별자 값으로 1차 캐시에서 엔티티를 조회
  3. 만약 1차 캐시에 엔티티가 없으면 데이터베이스에서 엔티티를 조회하고 1차 캐시에 저장
  4. 조회한 영속 엔티티(mergeMember)에 member 엔티티의 값을 채워 넣는다.(member 엔티티의 모든 값을 mergeMember에 밀어 넣는다. 이때 변경사항이 존재한다면 변경된다.)
  5. mergeMember를 반환.

비영속 병합

병합(merge)는 반드시 준영속 상태에서만 사용할 수 있는 기능이 아니다. 단지 방법에 차이가 있을 뿐이다.

비영속 상태인 경우 → 새로 생성하여 병합

준영속 상태인 경우 → 식별자 값으로 엔티티 조회하여 병합

 

삭제

  • 엔티티를 영속성 컨텍스트와 데이터베이스에서 삭제

EntityManger#remove 를 통해 삭제가 가능하다.

 

 

이상입니다.

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

[Spring/JPA] JPA Auditing  (0) 2023.02.17
[Spring/JPA] EntityGraph  (0) 2023.02.15
[Spring/JPA] 벌크 연산(Bulk Operation)과 EntityGraph  (0) 2023.02.13
[Spring/JPA] JPA 연관관계  (0) 2023.02.13
[Spring/JPA] JPA(Hibernate 구현체) DDL 전략  (0) 2022.06.17