본문 바로가기

IT/JPA

JPA Entity Manager를 알아보자

이번 시간에는 JPA EntityManager에 대해 알아보고자 합니다.
지난번에 알아보았던 JPA영속성 컨텍스트 글에서도 잠깐 등장한 녀석입니다.
EntityManager는 Java Persistence API의 일부이며 JPA 2.0 사양에 정의된 프로그래밍 인터페이스와 수명 주기 규칙을 구현합니다.
또한 EntityManager 의 API를 사용하여 영속성 컨텍스트에 액세스할 수 있습니다 .
이글에서는 EntityManager 의 구성, 유형 및 다양한 API를 살펴보겠습니다 .

- Gradle 종속성

Gradle에 아래와 같이 종속성을 추가해 줍니다.

implementation("org.springframework.boot:spring-boot-starter-data-jpa") //hibernate
runtimeOnly("mysql:mysql-connector-java") //mysql 드라이버

- EntityManager 주입

컨테이너 관리

@Configuration파일을 만들어서 전역으로 사용하게 합니다.

@Configuration
class QuerydslConfig(
    @PersistenceContext
    val entityManager: EntityManager
) {
    @Bean
    fun jpaQueryFactory(): JPAQueryFactory {
        return JPAQueryFactory(entityManager)
    }
}

애플리케이션 관리

수동으로 생성하고 수명주기를 관리합니다.

// 생성
entityManagerFactory:EntityManagerFactory = Persistence.createEntityManagerFactory("패키지명")

// 호출
fun getEntityManager():EntityManager {
  return entityManagerFactory.createEntityManager()
}

스레드 안정성

애플레이션 관리에서 스레드 제한 인스턴스는 직관적으로 만들 수 있으나 컨테이너 관리에서는 위에서 보듯 직관적이지 않습니다.

// 컨테이너에서 직관적이지 않음
@PersistenceContext
val entityManager: EntityManager

// 애플리케이션에서 직관적
entityManagerFactory:EntityManagerFactory = Persistence.createEntityManagerFactory("패키지명")
  • EntityManagerFactory에서의 인스턴스와 Hibernate의 SessionFactory인스턴스는 스레드로 부터 안점함

  • EntityManager 인스턴스는 스레드로 부터 안전하지 않음, 사용하 인스턴스 해제를 해줘야 합니다.

- Hibernate EntityManager

테스트 코드

class Test {

  @Test
  fun test() {
    val enf:EntityManagerFactory = Persistence.createEntityManagerFactory("persistence")
    val em:EntityManager = enf.createEntityManager()
    println("트랜잭션 시작")
    em.transaction.begin()

    val seller = Seller()
    seller.name = "gommi"
    println("데이터베이스에 저장")

    em.persist(seller)
    em.transaction.commit()
    println("판매자 ID"+ seller.id)

    // 아이디로 판매자 가져오기
    val seller = em.find(Seller.class, seller.id)
    printlin("가져온 데이터 : "+ seller.name+ " "+ seller.id)

    // 아이디로 판매자 가져오기 (전체)
    val sellerList: List<Seller> = em.createQuery("SELECT e FROM Seller e").resultList as List<Seller>

    sellerList?.forEach {
      println("SellerName :"+it.name + "SellerId : "+it.id)
    }

    // 엔티티 삭제
    em.transaction.begin()
    println("삭제할 판매자 아이디"+ seller.id)
    em.remove(seller)
    em.transaction.commit()

    // Entity Manager 닫기
    em.close()
    enf.close()
  }
}
  • EntityManagerFactory.createentityManager()는 사용할 EntityManager 인스턴스를 생성합니다.
    메서드를 호출 할 때마다 EntityManager의 새 인스턴스를 반환합니다.
  • em.transaction.begin() : 메서드는 먼저 현재 영속성 컨텍스트에서 트랜잭션을 가져온 다음 begin()메서드로 트랜잭션을 시작합니다.
  • em.persist(seller) : 데이터베이스에서 Seller객체를 유지하는 데 사용되었습니다.
  • em.transaction.commit() : 메서드는 트랜잭션을 가져온 다음 동일한 트랜잭션을 커밋하는 데 사용됩니다.
    이렇게 하면 데이터베이스에 모든 변경 사항이 커밋됩니다.
  • em.find() : 판매자 ID로 데이터베이스에서 엔티티를 찾는 데 사용되었습니다
  • em.remove() : 데이터베이스에서 엔티티를 제거해야 하는 경우에만 사용해야 합니다.
    참조하는 테이블이 있을경우 PersistenceException 에러가 발생하며 rollback됩니다.
  • em.close(), enf.close : EntityManager와 EntityManagerFactory 를 닫는데 사용되었습니다 사용한 리소스는 즉시 닫아줘야 합니다.

정리

이상으로 JPA EntityManager에 대해 알아보았습니다.

이 글에서는 다루지 않았는데 먼저 Entity의 생명주기에 대해서도 알아두시길 권해 드리며

나중에 Entity생명주기에 관한 글도 써보도록 하겠습니다.