개인공부
[ JPA ] JPA Entity, EntityManagerFactory, EntityManager, Persistence context
KEEMSY
2024. 2. 11. 17:07
개요
이번 정리에서는 JPA를 이해하고 사용하기 위한 내용으로, JPA의 엔티티 매핑, 엔티티 매니저 팩토리와 엔티티 매니저의 역할 및 사용법, 그리고 영속성 컨텍스트의 이해와 작동 원리에 대한 설명 을 중심으로 정리 한다.
내용 구성
- JPA Entity 생성
- 엔티티 매니저 팩토리(EntityManagerFactory)
- 엔티티 매니저(EntityManager)
- 영속성 컨텍스트(Persistence context)
JPA Entity 생성
@Entity // DB 테이블과 매핑 대상
@Table(name="user") // user 테이블과 매핑
public class User {
@Id // 식별자에 대응
private String email; // email 칼럼과 매핑
private String name; // name 칼럼과 매핑
@Cloumn(name="create_at") // create_date 칼럼과 매핑
private LocalDateTime createDate;
}
- Entity 애노테이션은 데이터베이스 테이블과 맵핑할 클래스이고, Table 어노테이션은 맵핑할 테이블명, Id 어노테이션은 테이블의 PK에 대응하는 컬럼을 지정한다.
- 또한 필드명과 컬럼 명이 다를 경우 Column 애노테이션을 이용해서 맵핑 할 컬럼 이름을 지정하여야 한다.
엔티티 매핑과 관련된 어노테이션은 다른 포스팅에서 작성한다.
@Repository
public class UserRepository {
@PersistenceUnit
private EntityManagerFactory emf;
//@PersistenceContext 이것을 더 많이 사용함
//EntityManager em;
public void createUser(String email, String name) {
EntityManager em = emf.createEntityManager();
EntityTransaction transaction = em.getTransaction();
try {
transaction.begin();
User user = new User(email, name, LocalDateTime.now());
em.persist(user);
transaction.commit();
} catch (Exception e) {
if (transaction.isActive()) {
transaction.rollback();
}
} finally {
if (em != null) {
em.close();
}
}
}
public User getUser(String email) {
EntityManager em = emf.createEntityManager();
try {
return em.find(User.class, email);
} finally {
if (em != null) {
em.close();
}
}
}
}
- 이런식으로 코드를 작성하는 일은 거의 없으나(Spring JPA에서 알아서 해줌), JPA 만 사용하는 경우에는 이렇게 해야 함.
- EntityManager 사용 후에는 반드시 close() 메서드를 호출하여 자원을 반환해야 한다.
- 모든 프로그램이 종료될 때는 EntityManagerFactory도 함께 close() 해야 한다.
엔티티 매니저 팩토리(EntityManagerFactory)
- 주 목적은 EntityManager 인스턴스를 관리하는 것이다.
- EntityManagerFactory 생성시 커넥션 풀도 함께 생성한다.
- 같은 EntityManagerFactory를 통해 생성되는 EntityManager는 같은 database에 접속한다.
- 한 번 생성 후 어플리케이션 전체에서 공유된다.
- EntityManagerFactory는 스레드에 안전(thread-safe)하다. 즉, 여러 스레드에서 동시에 EntityManager를 생성하는 것이 하다.
- EntityManagerFactory는 생성 비용이 높다. 따라서 애플리케이션에서는 보통 한 번만 생성하고 재사용한다.
- EntityManagerFactory를 종료(close)하면, 이에 연결된 모든 EntityManager 인스턴스도 종료된다. 따라서 EntityManagerFactory를 종료하기 전에 모든 EntityManager가 닫혔는지 확인해야 한다.
- @PersistenceUnit 을 통해 EntityManagerFactory를 얻을 수 있다.
하지만, @PersistenceContext 를 통해 EntityManager 를 주입 받아 사용할 수 있기 때문에 잘 사용하지 않는다.
엔티티 매니저(EntityManager)
// 방법 1. @PersistenceContext 사용
@PersistenceContext
private EntityManager em;
// 방법 2. EntityManagerFactory 에서 가져오기
@PersistenceUnit
private EntityManagerFactory emf;
EntityManager em = emf.createEntityManager();
em.find(); // 엔티티 조회
em.persist(); // 엔티티 저장
em.remove(); // 엔티티 삭제
em.flush(); // 영속성 컨텍스트 내용을 데이터베이스에 반영
em.detach(); // 엔티티를 준영속 상태로 전환
em.merge(); // 준영속 상태의 엔티티를 영속상태로 변경
em.clear(); // 영속성 컨텍스트 초기화
em.close(); // 영속성 컨텍스트 종료
- 엔티티를 저장, 수정, 삭제, 조회등 엔티티와 관련된 작업을 수행한다.
- Application-managed entity manager: 다음과 같은 코드로 엔티티매니져를 생성 및 제어한다.
- EntityManager 인스턴스 자체는 스레드에 안전하지 않으므로, 각 스레드는 자신만의 EntityManager를 사용해야 한다.
영속성 컨텍스트(Persistence context)
em.persist(entity); // 엔티티를 영속성 컨텍스트에 저장
- 어플리케이션과 데이터베이스 사이에 존재하는 논리적인 개념으로 엔티티를 저장하는 환경을 의미한다.
- 엔티티매니저를 통해서만 접근이 가능하다.
- 영속성 컨텍스트에 존재하는 엔티티는 플러시 호출시 데이터베이스에 반영 된다.
- entityManger.flush() 로 플러시 직접 호출
- 트랜젝션 커밋(commit) 시 플러시 자동 호출
- JPQL 쿼리 실행 시 플러시 자동 호출
- QueryDSL 실행 시, JPA 의 플러시 모드를 따름
- 영속성 컨텍스트의 장점
- 1차 캐시: 엔티티 조회시 영속성 컨테스트에 존재하면 바로 리턴, 없으면 데이터베이스 조회 후 리턴.
- 동일성(==)보장: 조회시 항상 같은 엔티티 인스턴스를 리턴(주소값이 같음)
- 트랜잭션을 지원하는 쓰기 지연(Transactional write-behind): 트랜젝션 커밋 될때까지 내부 쿼리저장소에 모아뒀다가 한번에 실행
- 변경감지(Dirty Checking): 엔티티의 스냅샷을 유지하면서 엔티티의 변경사항을 체크한다. update쿼리가 항상 같음.
- 지연로딩(Lazy Loading): 연관된 엔티티를 모두 불러오는 것이 아니라, 실제 호출될때 로딩되도록 지원(프록시 객체 사용)
요약
- JPA에서는 @Entity 어노테이션을 사용해 클래스를 데이터베이스 테이블과 맵핑하고, @Table, @Id,@Column 등의 어노테이션을 사용해 테이블명, PK, 컬럼명 등을 지정할 수 있다.
- 엔티티 매니저 팩토리(EntityManagerFactory)는 엔티티 매니저 인스턴스를 관리하고, 같은 팩토리를 통해 생성되는 엔티티 매니저는 같은 데이터베이스에 접속한다.
- 엔티티 매니저 팩토리는 스레드에 안전하며, 애플리케이션에서는 한 번만 생성하고 재사용하는 것이 일반적 이다.
- 엔티티 매니저(EntityManager)는 엔티티를 저장, 수정, 삭제, 조회 등의 작업을 수행하며, 각 스레드는 자신만의 엔티티 매니저를 사용해야 한다. 일반적으로 @PersistenceContext 를 통해 엔티티 매니저를 주입 받아 사용한다.
- 영속성 컨텍스트(Persistence Context)는 애플리케이션과 데이터베이스 사이에 존재하는 논리적인 개념으로, 엔티티를 저장하는 환경을 의미한다.
- 영속성 컨텍스트에 존재하는 엔티티는 플러시 호출시 데이터베이스에 반영되며, 1차 캐시, 동일성 보장, 변경 감지, 지연 로딩 등의 장점을 제공한다.
728x90