Backend study/JPA
영속성 관리
adulty22
2024. 10. 17. 13:05
JPA에서 영속성 관리는 애플리케이션이 데이터베이스와 상호작용하는 객체(엔티티)를 어떻게 관리하고, 해당 데이터를 어떻게 데이터베이스에 반영할지 결정하는 중요한 개념이다. JPA의 영속성 관리는 데이터베이스와 메모리 사이에서 엔티티 객체를 효율적으로 관리하여 성능을 최적화하고 데이터 일관성을 유지하는 역할을 한다.
1. 엔티티 매니저 팩토리(EntityManagerFactory)와 엔티티 매니저(EntityManager)
JPA에서 영속성 관리는 주로 EntityManager와 EntityManagerFactory를 통해 이루어진다. 이 두 가지는 JPA에서 핵심적인 역할을 하는 컴포넌트로, 각각의 역할과 기능을 이해하는 것이 중요하다.
엔티티 매니저 팩토리(EntityManagerFactory)
- EntityManagerFactory는 JPA에서 영속성 유닛(Persistence Unit)을 관리하는 팩토리 클래스이다.
- 애플리케이션이 실행될 때 데이터베이스와 연결되는 설정 정보를 바탕으로 EntityManager 객체를 생성하는 역할을 한다.
- 하나의 애플리케이션 내에서 여러 데이터베이스에 연결할 수 있도록 지원하며, 일반적으로 애플리케이션 당 하나의 EntityManagerFactory를 생성하고 애플리케이션이 종료될 때까지 유지된다.
- 리소스를 많이 사용하는 객체이므로, 한 번만 생성하고 공유하는 것이 일반적인 사용 방법이다.
EntityManagerFactory emf = Persistence.createEntityManagerFactory("persistenceUnitName");
엔티티 매니저(EntityManager)
- EntityManager는 엔티티의 생명 주기를 관리하고, 데이터베이스와 상호작용하는 인터페이스이다.
- 엔티티의 등록, 수정, 삭제, 조회 같은 데이터베이스 작업을 담당하며, 내부적으로 영속성 컨텍스트를 이용하여 엔티티를 관리한다.
- 스레드에 안전하지 않기 때문에, 요청마다 새로운 EntityManager를 생성하여 사용하는 것이 원칙이다. 이를 통해 트랜잭션을 처리하고 영속성 컨텍스트를 관리한다.
EntityManager em = emf.createEntityManager();
2. 영속성 컨텍스트(Persistence Context)
영속성 컨텍스트는 EntityManager가 엔티티 객체를 관리하는 일종의 메모리 공간이다. 여기에는 애플리케이션에서 관리하는 영속 상태의 엔티티가 저장된다.
영속성 컨텍스트의 역할
- 엔티티의 상태 관리: 영속성 컨텍스트는 데이터베이스와 상호작용하는 엔티티 객체를 관리한다. 애플리케이션은 EntityManager를 통해 엔티티를 조회하거나 저장할 때, 영속성 컨텍스트에 있는 객체를 활용한다.
- 1차 캐시: 영속성 컨텍스트는 엔티티를 메모리에 캐싱한다. 동일한 트랜잭션 내에서 같은 엔티티를 여러 번 조회하더라도 데이터베이스에 불필요하게 접근하지 않고 캐시된 데이터를 활용한다.
- 변경 감지(Dirty Checking): 영속성 컨텍스트는 관리 중인 엔티티의 상태 변화를 감지하고, 트랜잭션이 끝날 때 자동으로 변경된 사항을 데이터베이스에 반영한다.
영속성 컨텍스트를 활용한 예시
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
Member member = em.find(Member.class, 1L); // 1차 캐시에 저장
member.setName("Updated Name"); // 변경 감지
em.getTransaction().commit(); // 트랜잭션 종료 시점에 변경 사항을 DB에 반영
3. 엔티티의 생명주기(Entity Life Cycle)
JPA에서 엔티티 객체는 여러 가지 생명주기 상태를 가진다. 각 상태에 따라 JPA가 엔티티를 관리하는 방식이 달라진다.
1) 비영속(New, Transient)
- 엔티티 객체가 JPA와 전혀 연관되지 않은 상태이다.
- EntityManager를 통해 저장되지 않았고, 영속성 컨텍스트와도 관련이 없다.
- 단순히 메모리상에서 생성된 객체일 뿐, 데이터베이스에 저장되지 않은 상태이다.
Member member = new Member(); // 비영속 상태
2) 영속(Managed)
- 엔티티 객체가 EntityManager를 통해 영속성 컨텍스트에 저장된 상태이다.
- 영속성 컨텍스트가 엔티티를 관리하며, 변경 사항이 자동으로 감지되어 트랜잭션이 끝날 때 데이터베이스에 반영된다.
- 1차 캐시에 저장되어 동일한 트랜잭션 내에서 재사용된다.
em.persist(member); // 영속 상태
3) 준영속(Detached)
- 영속성 컨텍스트가 더 이상 엔티티를 관리하지 않는 상태이다.
- 트랜잭션이 끝나거나 EntityManager.clear() 또는 EntityManager.detach() 메서드를 호출하면 엔티티는 준영속 상태가 된다.
- 더 이상 변경 사항이 감지되지 않고, 데이터베이스와 동기화되지 않는다.
em.detach(member); // 준영속 상태
4) 삭제(Removed)
- 엔티티 객체가 삭제되어 영속성 컨텍스트와 데이터베이스에서 삭제된 상태이다.
- EntityManager.remove()를 호출하여 엔티티를 삭제한다.
em.remove(member); // 삭제 상태
4. 영속성 컨텍스트의 특징
1) 1차 캐시
- 영속성 컨텍스트는 1차 캐시로 엔티티를 관리한다. 즉, 영속성 컨텍스트에 있는 엔티티는 메모리 내에 저장되며, 같은 트랜잭션 내에서는 동일한 객체를 여러 번 조회할 경우 데이터베이스에 재조회하지 않고 캐시된 엔티티를 반환한다.
2) 동일성(identity) 보장
- 같은 트랜잭션 내에서 동일한 영속성 컨텍스트는 같은 엔티티 객체를 반환한다. 즉, 같은 id로 조회된 엔티티는 동일한 인스턴스로 보장된다.
3) 트랜잭션 쓰기 지연(transactional write-behind)
- 영속성 컨텍스트는 엔티티 변경 사항을 데이터베이스에 즉시 반영하지 않고, 트랜잭션이 커밋될 때 한 번에 반영한다. 이를 통해 여러 쿼리를 하나의 트랜잭션으로 묶어 효율성을 높인다.
5. 플러시(Flush)
Flush는 영속성 컨텍스트의 변경 내용을 데이터베이스에 동기화하는 과정이다. 즉, 엔티티의 변경 사항을 데이터베이스에 반영하지만, 트랜잭션이 종료되지는 않는다.
플러시가 발생하는 시점
- 트랜잭션이 커밋될 때: 트랜잭션이 커밋되기 전에 자동으로 플러시가 일어나서 영속성 컨텍스트에 있는 모든 변경 사항이 데이터베이스에 반영된다.
- JPQL 실행 시: JPQL 쿼리가 실행될 때, 쿼리의 정확성을 보장하기 위해 자동으로 플러시가 발생한다.
- 수동으로 호출: EntityManager.flush()를 호출하여 수동으로 플러시할 수 있다.
플러시와 영속성 컨텍스트
- 플러시는 영속성 컨텍스트를 비우는 것이 아니라, 변경 사항을 데이터베이스에 반영할 뿐이다. 플러시 이후에도 엔티티는 여전히 영속성 컨텍스트에 남아있고, 변경 감지가 계속 이루어진다.
6. 준영속 상태(Detached State)
준영속 상태란, 엔티티가 한 번 영속성 컨텍스트에 의해 관리되었지만 현재는 더 이상 관리되지 않는 상태를 말한다.
준영속 상태로 변하는 방법
- EntityManager.detach(): 특정 엔티티를 영속성 컨텍스트에서 분리하여 준영속 상태로 만든다.
- EntityManager.clear(): 영속성 컨텍스트의 모든 엔티티를 준영속 상태로 만든다.
- 트랜잭션 종료: 트랜잭션이 끝나면 영속성 컨텍스트가 종료되면서 엔티티는 준영속 상태로 변한다.
준영속 상태의 특징
- 변경 감지가 일어나지 않음: 준영속 상태가 되면 JPA는 해당 엔티티를 더 이상 관리하지 않으므로, 변경 사항을 감지하지 않는다.
- 데이터베이스와 동기화되지 않음: 영속성 컨텍스트의 관리 대상이 아니므로, 해당 엔티티의 변경 내용이 데이터베이스에 반영되지 않는다.
준영속 상태를 다시 영속 상태로 전환하는 방법
- merge() 메서드를 통해 준영속 상태의 엔티티를 다시 영속성 컨텍스트에서 관리할 수 있다. merge()는 준영속 상태의 엔티티를 받아서 새로운 영속 상태의 엔티티로 변경하고, 변경된 사항을 데이터베이스에 반영한다.
Member mergedMember = em.merge(detachedMember);
- 영속성 관리는 JPA의 핵심 개념으로, 엔티티 객체의 생명 주기를 관리하고 데이터베이스와의 상호작용을 추상화한다.
- EntityManagerFactory는 영속성 유닛을 관리하는 팩토리이며, EntityManager는 엔티티의 생명주기를 관리하고 데이터베이스와 상호작용하는 주요 인터페이스이다.
- 영속성 컨텍스트는 엔티티를 관리하는 메모리 공간으로, 1차 캐시, 동일성 보장, 변경 감지와 같은 기능을 제공한다.
- 플러시는 영속성 컨텍스트의 변경 내용을 데이터베이스에 반영하는 과정이며, 트랜잭션 커밋 시 자동으로 수행된다.
- 준영속 상태는 엔티티가 더 이상 영속성 컨텍스트에 의해 관리되지 않는 상태로, merge()를 통해 다시 영속 상태로 전환할 수 있다.
728x90