Akashic Records

Spring Data JPA - EntityManager 본문

Spring.io

Spring Data JPA - EntityManager

Andrew's Akashic Records 2024. 11. 26. 14:59
728x90

Spring Data JPA(Spring Data Java Persistence API)

 

EntityManager

EntityManager는 JPA(Java Persistence API)의 핵심 인터페이스 중 하나로, 데이터베이스와 상호작용하여 엔티티를 관리하는 역할을 합니다. Spring Data JPA에서 많이 자동화된 방식으로 처리되기 때문에 EntityManager를 직접 사용할 일이 많지는 않지만, JPA의 기본적인 메커니즘을 이해하거나 복잡한 커스터마이징이 필요한 경우 EntityManager를 직접 사용하는 것이 유용할 수 있습니다.

  • EntityManager는 JPA에서 엔티티를 관리하는 핵심 역할을 수행합니다.
  • 엔티티의 생명주기(영속, 비영속, 분리, 제거)를 관리하고, 데이터베이스와의 CRUD 작업을 간단하게 수행할 수 있도록 합니다.
  • JPQL 쿼리를 사용하거나 트랜잭션 경계를 관리하여 데이터의 일관성을 유지하는 데 기여합니다.

주요 기능 및 역할

EntityManager는 JPA에서 제공하는 주요 기능들을 수행하며, 엔티티(데이터베이스의 테이블과 매핑된 자바 객체)를 관리하는 데 필수적인 여러 메서드를 제공합니다. 주요 기능은 다음과 같습니다:

  1. 엔티티의 생명주기 관리:
    • EntityManager는 엔티티의 생명주기를 관리합니다. 엔티티의 생명주기에는 다음과 같은 상태가 있습니다.
      • Transient: 데이터베이스와 전혀 연결되지 않은 상태.
      • Persistent: EntityManager에 의해 관리되고 있으며, 데이터베이스에 매핑된 상태.
      • Detached: EntityManager에서 분리된 상태로, 더 이상 데이터베이스와 연결되지 않는 상태.
      • Removed: 엔티티가 삭제되기 위해 표시된 상태.
  2. CRUD 작업 수행:
    • 엔티티를 데이터베이스에 저장, 조회, 업데이트, 삭제하는 작업을 수행할 수 있습니다.
  3. 쿼리 실행:
    • JPQL(Java Persistence Query Language)을 사용하여 데이터베이스로부터 데이터를 조회하거나 업데이트하는 쿼리를 실행할 수 있습니다.
  4. 트랜잭션 관리:
    • EntityManager는 트랜잭션의 경계를 지정하여 데이터를 안전하게 관리하고 일관성을 유지하는 데 중요한 역할을 합니다.

주요 메서드

EntityManager에서 자주 사용되는 메서드를 간단히 설명해 보겠습니다.

  1. persist(Object entity):
    • 엔티티를 영속성 컨텍스트에 추가합니다. 이 엔티티는 데이터베이스에 저장됩니다.
      User user = new User();
      user.setName("John");
      entityManager.persist(user);
      위 코드는 User 엔티티를 데이터베이스에 추가하는 역할을 합니다.
  2. find(Class<T> entityClass, Object primaryKey):
    • 데이터베이스에서 엔티티를 기본 키를 사용해 조회합니다. 이 메서드는 영속성 컨텍스트에서 관리되는 엔티티를 반환합니다.
      User user = entityManager.find(User.class, 1L);
      find 메서드는 User 엔티티를 ID가 1인 엔티티로 조회합니다.
  3. merge(Object entity):
    • 변경된 엔티티를 영속성 컨텍스트로 다시 결합하여 업데이트합니다. 주로 Detached 상태에 있는 엔티티를 데이터베이스에 다시 반영하고자 할 때 사용합니다.
      User detachedUser = new User();
      detachedUser.setId(1L);
      detachedUser.setName("Jane");
      entityManager.merge(detachedUser);
      위 코드는 Detached 상태에 있는 User 객체의 변경사항을 영속성 컨텍스트에 반영하고, 데이터베이스를 업데이트합니다.
  4. remove(Object entity):
    • 영속성 컨텍스트에서 엔티티를 제거하고, 데이터베이스에서도 삭제합니다.
      User user = entityManager.find(User.class, 1L);
      entityManager.remove(user);
      위 코드에서는 ID가 1인 User 엔티티를 데이터베이스에서 삭제합니다.
  5. createQuery(String qlString):
    • JPQL 쿼리를 생성하여 데이터베이스와 상호작용합니다. 복잡한 조회나 조건에 따라 데이터를 필터링할 때 사용할 수 있습니다.
      List<User> users = entityManager.createQuery("SELECT u FROM User u WHERE u.age > 18", User.class).getResultList();
      이 코드는 User 엔티티 중 나이가 18세 이상인 사용자 목록을 조회합니다.
  6. flush():
    •  영속성 컨텍스트의 변경 내용을 데이터베이스에 즉시 반영합니다. 단, 트랜잭션이 완료되기 전에 강제로 반영할 때 사용합니다.
  7. clear():
    • 현재 영속성 컨텍스트 초기화하여 모든 엔티티를 Detached 상태로 만듭니다.

영속성 컨텍스트(Persistence Context)

EntityManager는 영속성 컨텍스트와 밀접한 관련이 있습니다. 영속성 컨텍스트란 엔티티의 상태를 관리하는 일종의 캐시 역할을 합니다. 이는 엔티티의 변경 사항이 즉시 데이터베이스에 반영되는 것이 아니라 트랜잭션이 커밋될 때 반영되도록 관리합니다.

  • 영속성 컨텍스트는 1차 캐시 역할을 하므로, 동일한 트랜잭션 내에서는 이미 조회된 엔티티를 재사용할 수 있습니다.
  • 따라서 엔티티 변경 시에는 데이터베이스와의 불필요한 통신을 줄여 성능이 향상됩니다.

트랜잭션과의 관계

EntityManager는 트랜잭션과 밀접하게 연결되어 있습니다. 엔티티의 변경 사항은 트랜잭션이 커밋될 때만 데이터베이스에 반영됩니다. 이러한 방식은 데이터 일관성을 유지하고, 작업 중간에 오류가 발생했을 때 롤백을 통해 데이터의 무결성을 보호합니다.

Spring에서는 보통 @Transactional 어노테이션을 사용하여 트랜잭션의 경계를 지정하며, 내부적으로 EntityManager가 이를 활용해 데이터베이스 작업을 안전하게 처리합니다.

EntityManager 사용 예시

@Service
public class UserService {

    @PersistenceContext
    private EntityManager entityManager;

    @Transactional
    public void createUser(String name) {
        User user = new User();
        user.setName(name);
        entityManager.persist(user);
    }

    @Transactional
    public User getUser(Long id) {
        return entityManager.find(User.class, id);
    }

    @Transactional
    public void updateUser(Long id, String newName) {
        User user = entityManager.find(User.class, id);
        user.setName(newName);
        entityManager.merge(user);
    }

    @Transactional
    public void deleteUser(Long id) {
        User user = entityManager.find(User.class, id);
        entityManager.remove(user);
    }
}

위의 코드에서는 EntityManager를 사용해 사용자 엔티티의 생성, 조회, 수정, 삭제를 수행합니다.

728x90

EntityManagerFactory

EntityManagerFactory는 JPA(Java Persistence API)의 핵심 컴포넌트 중 하나로, EntityManager 객체를 생성하는 팩토리 역할을 수행합니다. EntityManager는 실제 데이터베이스와 상호작용하여 엔티티의 상태를 관리하는 데 사용되기 때문에, 여러 개의 EntityManager를 효율적으로 생성하고 관리하는 것이 중요합니다. EntityManagerFactory는 이러한 목적을 위해 존재합니다.

  • EntityManagerFactory EntityManager 객체를 생성하는 팩토리 객체로, 애플리케이션 전반에 걸쳐 스레드 안전하게 관리됩니다.
  • EntityManager는 데이터베이스와 상호작용하며, 트랜잭션이나 데이터 작업에 사용됩니다.
  • EntityManagerFactory는 한 번만 생성하고, 여러 트랜잭션에서 재사용하는 것이 일반적입니다.
  • Spring Data JPA에서는 대부분의 EntityManager  EntityManagerFactory 작업이 자동화되어, 개발자는 주로 비즈니스 로직에 집중할 수 있습니다.

역할과 특징

  1. EntityManager 생성:
    • EntityManagerFactory는 여러 개의 EntityManager 인스턴스를 생성합니다. 각 EntityManager는 데이터베이스와 상호작용을 담당하는 개별적인 세션 같은 역할을 하며, 독립된 트랜잭션 관리를 할 수 있습니다.
    EntityManagerFactory emf = Persistence.createEntityManagerFactory("my-persistence-unit");
    EntityManager em = emf.createEntityManager();
    위 코드는 EntityManagerFactory를 통해 EntityManager 객체를 생성하는 과정을 보여줍니다. "my-persistence-unit"은 설정 파일(persistence.xml)에 정의된 영속성 유닛 이름입니다.

  2. 영속성 유닛 관리:
    • EntityManagerFactory는 JPA의 영속성 유닛(Persistence Unit)을 정의하고 관리합니다. 영속성 유닛은 특정 데이터베이스와의 연결 및 관련 엔티티 클래스를 하나의 논리적 단위로 묶은 것을 말합니다. 이를 통해 JPA는 다양한 데이터 소스를 쉽게 관리할 수 있습니다.
  3. 비용이 높은 리소스 관리:
    • EntityManagerFactory는 비용이 많이 드는 리소스를 관리하므로, 애플리케이션에서 한 번만 생성되고 필요할 때 재사용됩니다. 이는 데이터베이스와의 연결을 위한 초기 설정과 연결을 효율적으로 관리하기 위함입니다.
    • 보통 애플리케이션의 시작 단계에서 하나의 EntityManagerFactory를 생성하고, 종료 시에 이를 닫아야 합니다. EntityManager는 단기적으로 사용 후 즉시 닫는 방식으로 운영됩니다.
  4. 스레드 안전:
    • EntityManagerFactory는 스레드 안전하므로, 여러 스레드에서 동시에 사용해도 문제가 없습니다. 반면 EntityManager는 스레드 안전하지 않으므로, 각 트랜잭션마다 별도의 EntityManager를 사용하는 것이 일반적입니다.

주요 메소드

  • createEntityManager():
    • 새로운 EntityManager 인스턴스를 생성합니다. 이 메소드를 호출할 때마다 새로운 EntityManager가 만들어지므로 각 트랜잭션이나 데이터 작업에 대해 별도의 EntityManager를 사용할 수 있습니다.
      EntityManager em = entityManagerFactory.createEntityManager();
  • close():
    • EntityManagerFactory가 더 이상 필요하지 않을 때 리소스를 해제하는 데 사용됩니다. 보통 애플리케이션이 종료될 때 호출합니다.
      entityManagerFactory.close();

영속성 유닛(Persistence Unit)

EntityManagerFactory는 영속성 유닛을 기반으로 생성되며, 영속성 유닛은 persistence.xml 파일에 정의됩니다. 이 파일은 JPA 설정을 포함하며, 주로 다음과 같은 내용을 포함합니다:

  • 데이터베이스 연결 정보 (URL, 사용자 이름, 암호 등)
  • 사용할 엔티티 클래스들
  • 캐싱, 트랜잭션 타입과 같은 추가적인 설정들

예시 persistence.xml 파일:

<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence" version="2.1">
    <persistence-unit name="my-persistence-unit">
        <class>com.example.User</class>
        <properties>
            <property name="javax.persistence.jdbc.driver" value="com.mysql.cj.jdbc.Driver"/>
            <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/mydb"/>
            <property name="javax.persistence.jdbc.user" value="root"/>
            <property name="javax.persistence.jdbc.password" value="password"/>
        </properties>
    </persistence-unit>
</persistence>

 

EntityManagerFactory와 EntityManager의 차이

  • EntityManagerFactory: 여러 EntityManager 인스턴스를 생성할 수 있는 팩토리 객체입니다. 애플리케이션 시작 시 한 번 생성되며, 고정적으로 유지되는 경향이 있습니다.
  • EntityManager: 데이터베이스와 직접 상호작용하는 세션 객체입니다. 각각의 트랜잭션이나 데이터 작업마다 생성되고, 사용 후 닫혀야 합니다.

사용 예시

아래는 EntityManagerFactory와 EntityManager를 이용해 간단한 CRUD 작업을 수행하는 예시입니다.

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

public class Main {
    public static void main(String[] args) {
        // EntityManagerFactory 생성 (애플리케이션 시작 시)
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("my-persistence-unit");

        // EntityManager 생성 (데이터 작업 수행 시)
        EntityManager em = emf.createEntityManager();

        // 트랜잭션 시작
        em.getTransaction().begin();

        // 엔티티 생성 및 데이터베이스에 저장
        User user = new User();
        user.setName("John Doe");
        em.persist(user);

        // 트랜잭션 커밋
        em.getTransaction().commit();

        // EntityManager 닫기 (작업 완료 시)
        em.close();

        // 애플리케이션 종료 시 EntityManagerFactory 닫기
        emf.close();
    }
}

 

Spring에서의 사용

Spring Data JPA에서는 EntityManagerFactory와 EntityManager의 많은 부분이 자동화되어 있어 개발자가 직접 생성하거나 관리할 필요가 거의 없습니다. Spring은 애플리케이션 컨텍스트를 시작할 때 자동으로 EntityManagerFactory를 생성하고, 트랜잭션 범위 내에서 EntityManager를 관리해 줍니다.

 

대부분의 경우, 우리는 @Repository와 @Transactional을 사용해 트랜잭션과 데이터 접근을 쉽게 처리합니다. 필요할 경우 @PersistenceContext 어노테이션을 통해 EntityManager를 주입받아 사용할 수도 있습니다.

@Service
public class UserService {

    @PersistenceContext
    private EntityManager entityManager;

    public void createUser(String name) {
        User user = new User();
        user.setName(name);
        entityManager.persist(user);
    }
}



728x90
Comments