Spring :: EntityManager

2025. 8. 5. 09:20백엔드/Spring Framework

EntityManager 란

JPA(Java Persistence API)에서 엔티티(객체)와 데이터베이스 간의 상호작용을 관리하는 핵심 인터페이스

DB 작업(CRUD)을 객체 단위로 수행하게 해주는 매니저

 

 

■ 주요 역할

CRUD 수행

persist(), find(), remove(), merge() 등 메서드로 엔티티 저장/조회/삭제/갱신

 

JPQL 실행

객체 중심의 쿼리인 JPQL을 실행 (createQuery, createNamedQuery)

 

트랜잭션 관리

트랜잭션 범위 내에서 엔티티 상태를 관리

 

1차 캐시 관리

같은 트랜잭션 내에서 동일한 엔티티는 캐싱되어 있음 (영속성 컨텍스트)

 

엔티티 상태 관리

new, managed, detached, removed 상태를 추적하고 변경 감지 수행 (dirty checking)

 

 

 

 주요 메서드

persist(Object entity)

    → 엔티티를 영속 상태로 만들어 DB에 저장

find(Class<T> entityClass, Object primaryKey)

     → PK 기준으로 조회

remove(Object entity)

     → 엔티티 삭제

merge(Object entity)

     → 준영속 상태의 엔티티를 영속 상태로 병합

flush()

     → 영속성 컨텍스트의 변경 내용을 즉시 DB에 반영

clear()

     → 영속성 컨텍스트 초기화 (1차 캐시 비움)

createQuery(String jpql)

     → JPQL 또는 Native SQL 실행

createNativeQuery(String sql)

     → SQL 실행

 

 

 EntityManager 작동 원리

EntityManager는 내부적으로 영속성 컨텍스트 (Persistence Context) 를 유지함(1차 캐시)

이 1차 캐시를 이용해 DB에 접근하지 않고도 같은 엔티티를 여러 번 조회할 때 같은 인스턴스를 반환하게 해 준다.

EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();

Member member = new Member("userA");
em.persist(member); // INSERT SQL이 아직 DB에 날아가지 않음

Member findMember = em.find(Member.class, member.getId()); // 같은 객체 리턴 (1차 캐시 이용)

tx.commit(); // 이 시점에 INSERT SQL 실행됨 (flush)

em.close();

 

 

 

 EntityManager 사용시 장단점

장점

더 유연하고 세밀한 제어 가능 (JPQL, NativeQuery, 트랜잭션 범위 등)

JPA의 기본 스펙에 가장 가까운 방식으로 사용할 수 있음

단점

코드가 장황해질 수 있음 (Repository/Service 계층에서 반복되는 코드 많음)

자동화/추상화가 적음 (Spring Data JPA의 Repository처럼 간결하지 않음)

 

 EntityManager    vs    Spring Data JPA Repository

  EntityManager Spring Data JPA Repository
코드 제어 직접 쿼리/로직 제어 추상화된 인터페이스로 간결함
쿼리 JPQL 또는
Native Query 직접 작성
@Query , QueryDSL 사용
Specification 등 활용
생산성 직접 구현 필요 자동 구현으로 생산성 높음
테스트 용이성 높음 높음

 

개인적인 느낌

개인적으로 최근 진행했던 프로젝트에서 상품, 주문, 배송 로직을 담당하였을 때의 기준 경험으로

SQL 문법과 JPQL, 서브쿼리에 대한 이해가 어느정도 있으면 Spring Data JPA 만으로도 충분하였어서

딱히 EntityManager를 굳이 사용할 일은 없었다.

 

DB 문제라고 여겨지면 굳이 서비스로직을 들여다 볼 것 없이

→ JpaRepository 를 상속받은 Repository 인터페이스의 @Query() @NativeQuery() 문이 잘못되었다

→ MySQL 컬럼이 추가되지 않았는지, 타입이 잘못되었다

 

라는 쪽으로 범위가 좁혀져서 차라리 편했던것 같다.

그러나, 이후에는 필요할 수 있기에 EntityManager 가 필요한 경우를 적어 둔다.

 

 

 EntityManager 가 필요한 경우

→ Spring Data JPA로 해결되지 않는 복잡한 쿼리가 필요한 경우

→ 성능 최적화를 위해 flush/clear 제어, 벌크 연산, 네이티브 SQL 사용이 필요한 경우

→ 동적 쿼리 생성 시 Criteria API나 QueryDSL 등과 함께 사용

라고 하는데 아직 큰 규모로 해본 적이 없어서 추후에 성능 문제로는 필요할 수 있을 것 같다.