API/JPA

영속성 관리

시뻘건 튼튼발자 2024. 8. 17. 10:50
반응형

영속성 관리는 엔티티(Entity) 객체를 데이터베이스와 매핑하고, 엔티티의 생명주기를 관리하며, 영속성 컨텍스트(Persistence Context)를 통해 엔티티의 상태를 제어하는 데 사용된다. 이 글에서는 엔티티 매니저 팩토리와 엔티티 매니저, 영속성 컨텍스트, 엔티티 생명주기, 플러시, 준영속 상태와 같은 주요 개념을 포스팅한다.

 

1. 엔티티 매니저 팩토리와 엔티티 매니저

엔티티 매니저 팩토리(EntityManagerFactory)는 JPA에서 엔티티 매니저(EntityManager)를 생성하는 역할을 한다. 이는 애플리케이션이 시작될 때 한 번 생성되며, 애플리케이션이 종료될 때까지 유지된다.

엔티티 매니저 팩토리의 생성은 비용이 많이 들어가기 때문에 공유해서 사용하며 엔티티 매니저는 connection pool로부터 데이터베이스에 직접적으로 관여하기 때문에 스레드간 공유가 되어서는 안된다.

EntityManagerFactory emf = Persistence.createEntityManagerFactory("my-persistence-unit");
EntityManager em = emf.createEntityManager();

위 코드에서 my-persistence-unit은 persistence.xml 파일에 정의된 영속성 유닛이다. EntityManagerFactory는 여러 EntityManager를 생성할 수 있다.

엔티티 매니저(EntityManager)는 데이터베이스와의 작업을 처리하는 주요 인터페이스로, 엔티티의 CRUD(Create, Read, Update, Delete) 작업을 수행한다.

2. 영속성 컨텍스트란?

영속성 컨텍스트(Persistence Context)란 엔티티 매니저가 관리하는 엔티티 객체의 집합을 의미한다. 이는 메모리 내에서 엔티티를 관리하며, 데이터베이스와의 동기화를 통해 엔티티 상태를 반영한다.

영속성 컨텍스트는 엔티티를 관리하며, 동일한 트랜잭션 내에서는 동일한 엔티티 인스턴스를 제공한다. 이는 엔티티를 영속성 컨텍스트에 저장하고, 관리되는 엔티티를 통해 변경 사항을 추적할 수 있게 해준다.

3. 엔티티의 생명주기

[그림 1] 엔티티의 생명 주

엔티티는 JPA에서 다음과 같은 생명주기를 가진다:

  1. 비영속(New/Transient): 엔티티가 영속성 컨텍스트에 관리되지 않는 상태
  2. 영속(Managed): 엔티티가 영속성 컨텍스트에 저장되어 관리되는 상태
  3. 준영속(Detached): 엔티티가 영속성 컨텍스트에서 분리된 상태
  4. 삭제(Removed): 엔티티가 삭제되어 영속성 컨텍스트와 데이터베이스에서 제거될 상태

4. 영속성 컨텍스트의 특징

엔티티 조회

영속성 컨텍스트에서 엔티티를 조회하면, 동일한 트랜잭션 내에서 동일한 엔티티 인스턴스를 반환합니다. 이는 1차 캐시로 불리는 영속성 컨텍스트의 기본적인 기능 때문이다.

EntityManager em = emf.createEntityManager();
Member member = em.find(Member.class, 1L);
Member sameMember = em.find(Member.class, 1L);  // 같은 트랜잭션 내에서는 동일한 인스턴스
System.out.println(member == sameMember) // true

엔티티 등록

엔티티 매니저의 persist() 메서드를 호출하면 엔티티는 영속 상태로 전환되어 1차 캐시, 쓰기 지연 등 영속 컨텍스트의 특징을 이용할 수 있다.

Member member = new Member();
em.persist(member);  // 영속 상태로 변경

엔티티 수정

영속 상태의 엔티티는 엔티티 매니저가 자동으로 변경 사항을 추적하여 데이터베이스에 반영한다.

member.setName("New Name");  // 따로 update 메서드를 호출하지 않아도 DB에 반영됨

엔티티 삭제

영속성 컨텍스트에서 엔티티를 삭제하려면 remove() 메서드를 사용한다.

em.remove(member);  // 엔티티 삭제

5. 플러시

플러시(Flush)는 영속성 컨텍스트의 변경 사항을 데이터베이스에 동기화하는 과정이다. 이는 트랜잭션이 커밋되기 전에 자동으로 발생한다.

 

플러시 모드 옵션

플러시 모드는 FlushModeType.AUTO와 FlushModeType.COMMIT으로 설정할 수 있다. AUTO 모드에서는 트랜잭션 커밋 시 자동으로 플러시가 발생하고, COMMIT 모드는 커밋 시에만 플러시가 일어난다.

 

6. 정리

[그림 2] 영속 컨텍스트

 

엔티티를 영속화하면 해당 엔티티의 @Id값을 키로 가지고 엔티티를 값으로 가지는 영속 컨텍스트 내 1차 캐시라는 공간에서 관리된다. 이 때 영속 컨텍스트는 스냅샷을 떠서 초기값의 엔티티를 가지고 있다. 그리고 쓰기 지연 SQL 저장소라는 공간이 있는데 이 곳에 Query를 모아둔다. UPDATE문의 경우에는 1차 캐시의 엔티티와 스냅샷(초기값)을 비교하여 변경 감지를 하여 UPDATE문을 쓰기 지연 SQL 저장소에서 관리한다. 트랜잭션이 종료되거나 flush()가 실행되면 쓰기 지연 SQL 저장소에 있던 query들이 데이터베이스에 반영되고 커밋이 된다. 이 특징을 쓰기 지연이라 부른다. 내가 아무리 엔티티를 변경해도 flush되기 전까지는 영속 컨텍스트 내에서만 변경이 될 뿐, 데이터베이스에는 반영되지 않는다는 이야기이다.

반응형