[JPA] 영속성 관리 - 엔티티 매니저/팩토리, 영속성 컨텍스트, 엔티티 생명주기

JPA가 제공하는 기능은 크게

  1. 엔티티와 테이블을 매핑하는 설계 부분
  2. 매핑한 엔티티를 실제로 사용하는 부분

이렇게 두 가지로 나눌 수 있다.

엔티티 매니저는 엔티티와 관련된 모든 일(저장, 수정, 삭제, 조회 ...)을 처리한다. 

 

엔티티 매니저에 대해 자세히 알아보자. 

구현과 관련된 부분은 하이버네이트를 기준으로 설명한다.

📂 엔티티 매니저 팩토리 & 엔티티 매니저

엔티티 매니저 팩토리는 엔티티 매니저를 만드는 공장이다. 이를 생성하는 비용은 매우 크기 때문에 한 개만 만들어서 애플리케이션 전체에서 공유하도록 설계되어 있다. 반면에 엔티티 매니저를 생성하는 비용은 거의 들지 않는다. 

💡 엔티티 매니저 팩토리는 여러 스레드가 동시에 접근해도 안전하므로 서로 다른 스레드 간에 공유해도 되지만, 엔티티 매니저는 여러 스레드가 동시에 접근하면 동시성 문제가 발생하므로 스레드 간에 절대로 공유해서는 안된다. 

위 그림을 보면 하나의 EntityManagerFactory(Emf라 칭하겠다.)에서 다수의 EntityManager를 생성했다. EntityManager 1은 아직 데이터베이스 커넥션을 사용하지 않는데, 엔티티 매니저는 트랜잭션을 시작하는 것과 같이 데이터베이스 연결이 꼭 필요한 시점까지 커넥션을 얻지 않는다. 보통 트랜잭션을 시작할 때 커넥션을 획득한다. 

JPA 구현체들(하이버네이트 ...)은 Emf를 생성할 때 커넥션풀도 만드는데, 이는 J2SE 환경에서 사용하는 방법이다. 뒤에서 더 자세하게 알아보겠다.

📂 영속성 컨텍스트

영속성 컨텍스트(Persistence Context)란, 쉽게 말해서 '엔티티를 영구 저장하는 환경'이다. 

엔티티 매니저로 엔티티를 저장하거나 조회하면 엔티티 매니저는 영속성 컨텍스트에 엔티티를 보관하고 관리한다. 

em.persist(member);

위 코드를 기존에는 단순히 회원 엔티티를 저장한다고 표현했지만, 정확히 얘기하면 persist() 메소드엔티티 매니저를 사용해서 회원 엔티티를 영속성 컨텍스트에 저장하는 것이다. 

 

영속성 컨텍스트는 논리적인 개념에 가깝다. 엔티티 매니저를 생성할 때 하나 만들어진다. 엔티티 매니저를 통해 영속성 컨텍스트에 접근하고 관리할 수 있다.


📂 엔티티 생명주기

엔티티의 생명주기에 대해 알아보자. 엔티티에는 4가지 상태가 존재한다. 

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

아래 그림은 엔티티의 생명 주기를 나타낸 그림이다. 

📄 비영속

엔티티 객체를 생성했다. 현재는 순수한 상태로 아직 저장하지 않았다. 따라서 영속성 컨텍스트나 데이터베이스와는 전혀 관련이 없다. 이것을 비영속 상태라 한다. 아래를 참고하자.

// 객체를 생성한 상태(비영속)
Member member = new Member();
member.setId("member1");
member.setUsername("회원1");

em.persist() 호출 전, 비영속 상태

📄 영속

엔티티 매니저를 통해 엔티티를 영속성 컨텍스트에 저장(persist())했다. 이렇게 영속성 컨텍스트가 관리하는 엔티티를 영속 상태라 한다. 

결국 영속 상태라는 것은 영속성 컨텍스트에 의해 엔티티가 관리된다는 뜻이다.

em.find() 나 JPQL을 사용해서 조회한 엔티티도 영속성 컨텍스트가 관리하는 영속 상태이다. 
// 객체를 저장한 상태(영속)
em.persist(member);

em.persist() 호출 후, 영속 상태

📄 준영속

영속성 컨텍스트가 관리하던 영속 상태의 엔티티를 영속성 컨텍스트가 관리하지 않으면 준영속 상태가 된다. 특정 엔티티를 준영속 상태로 만들려면 em.detach( )를 호출하면 된다. 

em.close()를 호출해 영속성 컨텍스트를 닫거나, em.clear()를 호출해 영속성 컨텍스트를 초기화해도 준영속 상태가 된다. 

// 회원 엔티티를 영속성 컨텍스트에서 분리, 준영속 상태
em.detach(member);

📄 삭제 

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

// 객체를 삭제한 상태(삭제)
em.remove(member);

참고

자바 ORM 표준 JPA 프로그래밍(김영한 저)

'JPA' 카테고리의 다른 글

[JPA] 준영속  (0) 2023.04.27
[JPA] 플러시  (0) 2023.04.25
[JPA] 영속성 컨텍스트의 특징  (1) 2023.04.17
[JPA] 엔티티 매니저 설정 + 트랜잭션 관리 + 비즈니스 로직  (2) 2023.04.14
[JPA] 객체 매핑  (0) 2023.04.14