(이 게시글은 SpringBoot 환경을 기준으로 작성되었습니다.)
entityManager를 이해하기 위해서는 영속성 컨텍스트란 무엇인지 알 필요가 있는데 영속성 컨텍스트 관련글은 하단의 링크 게시글을 참고바란다.
JPA를 사용하기 위해서는 Database 구조와 맵핑된 Entity 들을 먼저 생성해야한다. 그리고 모든 JPA의 동작은 이 Entity들을 기준으로 돌아가게 되는데, 이 때 Entity들을 관리하는 역할을 하는 것이 EntityManager이다. 기술적으로 설명하자면 @Entity 어노테이션이 있는 객체들을 관리하며 EntityManager는 영속성 컨텍스트 영역에 두어 Entity 생애주기를 관리한다.
EntityManager의 특징은 영속성 컨텍스트와 겹치는 점이 몇가지 있는데 영속 엔티티의 동일성 보장, 변경감지, 쓰기 지연, 1차 캐시가 EntityManager와 특징이 겹친다.
영속성 컨텍스트에 등록된 Entity 객체의 @Id 어노테이션이 붙은 필드 값을 사용하여 Map<Id, Entity>형태로 저장한다. 어플리케이션에서 데이터 조회를 요청하면, EntityManager는 먼저 내부에 캐싱된 Entity가 있는지 확인한다. 데이터가 존재하면 DB에 쿼리를 전송하지 않고, 캐싱된 Entity를 반환하기 때문에 쿼리 성능이 최적화된다.
EntityManager는 내부적으로 Entity를 저장한다, 따라서 동일한 Entity를 요청할 때에는 동일한 Entity를 반환하기 때문에 동일성이 보장된다.
EntityManager에서 commit()을 호출할 때 한번에 전달한다. 이러한 방식은 데이터를 처리하는 과정에서 의도치 않은 에러가 발생할 경우 roll-back이 용이하며, 네트워크 비용을 최소화할 수 있다는 장점을 지닌다.
쉽게 말하면 만약 10000번의 쿼리를 10000번 수행한다면 DB와 10000번 통신이 필요하다. 하지만 쿼리를 10개씩 묶어서 처리한다면 1000번만 수행하면 되기 때문에 네트워킹 횟수가 현저히 줄어들고 서비스의 부하가 감소하게 된다.
EntityManager에 등록된 Entity에 변경이 감지되면 트랜잭션이 커밋되는 시점에 1차 캐시를 비교를 통해 자동으로 Update 쿼리로 변경된다.
@ManyToOne 같이 다대일 관계를 가진 Entity를 조회할 때, 실제로 해당 Entity의 데이터에 직접 접근하는 시점에 쿼리를 실행하는 방식을 의미한다. 지연로딩 을 통해 EntityManager는 불필요한 쿼리를 최소화한다.
(만약 지연로딩을 안하면 즉시호출되어 불필요한 쿼리가 발생하고 이름 1+n현상이라고 한다.)
다음과 같이 EntityManger는 영속성 컨텍스트와 연관이 깊은 만큼 그 특징 또한 겹치는 부분이 많다.
EntityManagerFactory는 EntityManager를 만드는 클래스로 애플리케이션 전체중 1개만 생성이 가능하다 그래서 애플리케이션 전체에 공유하도록 설계되어있다.
SpringBoot로 프로젝트를 생성하면 EntityManagerFactory를 생성 안하고 바로 EntityManager를 생성하는 것을 볼 수 있다. 그 이유는 만약 본인 프로젝트에 Spring-data-jpa를 종속 시켰다면 properties 파일 혹은 yml파일에 데이터베이스 정보만 등록하면 별도로 설정이 필요없이 EntityManager를 사용할 수 있다.
원래라면 이렇게 선언해야 한다.
// EntityManagerFactory 생성
EntityManagerFactory emf = Persistence,createEntityManagerFactory("Hi");
// EntityManager 생성
EntityManager em = emf.createEntityManager();
SpringBoot에서 EntityManagerFactory를 직접 사용하지 않는 이유는 다음과 같다.
지금 설명할 EntityManager는 정확히 말하면 Spring에서 사용하는 EntityManager이다. Spring에서는 EntityManager를 위의 EntityManagerFactory에서 한 것 처럼 EntityManager를 선언하지 않고 생성자 주입방식을 사용해 EntityManager를 선언한다.
import org.springframework.stereotype.Repository;
import org.springframework.beans.factory.annotation.Autowired;
import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
@Repository
public class memberService {
// 영속성 컨텍스트에 등록한 선언방식
@PersistenceContext
private EntityManager em;
// Autowire를 활용한 생성자 주입 선언방식
@Autowired
private EntityManager em;
// 상수 생성자 주입 선언방식
private final EntityManager em;
memberService(EntityManager em){
this.em = em;
}
}
Spring에서는 EntityManager를 사용한다면 @PersistenceContext 어노테이션 대신 @Autowired를 활용한 생성자 주입 아니면 일반적인 생성자 주입방식을 사용한다. JPA의 특정기능이 필요하거나 의도를 명시적으로 하고싶은 경우에는 @PersistenceContext 어노테이션을 사용한다.
EntityManager가 JPA를 사용하는 기본방법이기에 EntityManager의 이론부분 설명이 필요하다고 느껴 이론설명 글을 작성했다, 다음 글에서는 EntityManager를 실제로 사용하는 것을 작성하려고 한다.
https://bnzn2426.tistory.com/143
https://velog.io/@koo8624/Spring-EntityManager
https://velog.io/@juhyeon1114/JPA-영속성-컨텍스트-이해하기-w.-Entity-manager