JPA에서 가장 중요한 2가지 1. 객체와 관계형 DB 매핑, 2. 영속성 컨텍스트 중 영속성 컨텍스트에 대해 알아보고, Entity의 4가지 상태에 대해 알아봅시다.
Entity
는 데이터베이스 테이블과 1대1로 매핑되는 클래스를 의미합니다.
테이블의 pk와 매핑되는 고유한 식별값(@ID)를 가지고 있습니다.
영속성 컨텍스트는 엔티티를 영구 저장하는 환경
입니다.
애플리케이션과 DB 사이에서 객체를 관리하는 논리적인 개념입니다.
JPA에서는 EntityManagerFactory
를 하나 가지고 있고, 트랜잭션이 수행될때 마다 EntityManager
를 생성합니다.
엔티티 매니저
를 통해 영속성 컨텍스트에 접근할 수 있습니다.
em.persist()
메서드로 엔티리를 저장할때 등록되며
em.find()
로 조회할 때 1차 캐시에에 해당 엔티티가 있으면 해당 엔티티를 반환하고 없으면 영속성 컨텍스트에 등록하고 반환합니다.
// id 기준, 1L, 2L 엔티티는 저장되어있습니다.
// 새로운 객체 생성
Member member = new Member(3L, "mebmerC");
// 영속성 컨텍스트에 등록
em.persist(member);
// find 조회 후 영속성 컨텍스트에 등록
em.find(Member.class, 1L);
영속성 컨텍스트는 엔티티
를 식별자 값
(@ID로 테이블의 기본 키와 매핑한 값)으로 구분합니다.
따라서, 영속 상태는 식별자 값이 반드시 있어야합니다.
플러시는 영속성 컨텍스트의 변경내용을 데이터베이스에 동기화하는 것을 의미합니다.
플러시가 수행되는 경우 3가지
엔티티는 4가지 상태를 가집니다.
영속성 컨텍스트와 전혀 관계없는 상태
영속성 컨텍스트에 등록된 상태
삭제된 상태
영속성 컨텍스트에 저장되었다가 분리된 상태
비영속 상태에 가깝다
영속성 컨텍스트가 제공하는 어떠한 기능도 동작하지 않는다.
(지연로딩, 1차 캐시, 쓰기 지연, 변경 감지)
식별자 값을 가지고 있다.
비영속 상태는 식별자 값이 없지만, 준영속 상태는 이미 한번 영속 상태였으므로 식별자 값(ID)을 가지고 있다.
em.detach(entity): 특정 엔티티만 준영속 상태로 전환
em.clear() 영속성 컨텍스트를 완전히 초기화
em.close() 영속성 컨텍스트를 종료
현재 테이블 상태, 식별자
값 기준 3개의 데이터가 들어있습니다.
package helljpa;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
public class JpaMain {
public static void main(String[] args) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();;
try {
// 1. 비영속 상태
// 새로운 객체 생성
Member member4 = new Member(4L, "mebmerD");
// 2. 영속 상태
em.persist(member4);
// 2. 영속 상태
// find 조회, 1차 캐시에 없기 때문에 영속성 컨텍스트에 등록
Member member1 = em.find(Member.class, 1L);
Member member2 = em.find(Member.class, 2L);
// 3. 준영속 상태
// 영속성 컨텍스트에서 분리
em.detach(member1);
// 4. 삭제 상태
// 영속된 상태만 삭제할 수 있습니다.
em.remove(member2);
tx.commit();
} catch (Exception e) {
// 실패하면 롤백
tx.rollback();
} finally {
// enity manager가 데이터 커넥션을 물고있다. 꼭 닫아준다.
em.close();
}
emf.close();
}
}