JPA 기본 3
영속성 컨텍스트
- JPA를 이해하는데 가장 중요한 용어
엔티티를 영구 저장하는 환경
이라는 뜻이다.- 영속성 컨텍스트는 논리적인 개념이다.
- 엔티티 매니저를 통해서 영속성 컨텍스트에 접근 가능하다.
J2SE 환경
- EntityManager와 PersistenceContext가 1대 1로 매핑된다.
Entity의 생명주기
비영속 (new/transient)
- PersistenceContext와 전혀 관계 없다.
- 새로운 상태다.
1
2
3
// JPA와는 전혀 연관 관계가 없는 상태다.
Member member = new Member();
member.setId("memberA");
영속 (managed)
- PersistenceContext에 관리되는 상태다.
1
entityManager.persist(member); // 영속성 컨텍스트가 관라하게 된다. 아직 DB에 저장되지는 않은 상태다. (차후 저장)
준영속 (detached)
- PersistenceContext에 저장되었다가 분리된 상태다.
1
entityManager.detach(member); // 영속성 컨텍스트에서 member를 분리한다.
삭제 (removed)
- 삭제된 상태
1
entityManager.remove(member); // member 객체를 DB에서 지우겠다는 요청을 보낸다.
영속성 컨텍스트의 이점
1차 캐시
1
2
3
4
5
6
7
8
9
10
11
12
13
// 엔티티를 생성한 상태 - 비영속
Member m = new Member();
m.setId("m1");
m.setName("merry");
// 영속 상태로 전환, 1차 캐시에 저장된다.
em.persist(m);
// 조회 - 1차 캐시에서 조회한다. (즉, 조회하는 SQL을 날리지 않는다는 것이다.)
Member findedMember1 = em.find(Member.class, "m1");
// DB에서 조회, 1차 캐시에 없으므로 조회용 SQL을 날린다.
Member findedMember2 = em.find(Member.class, "m2");
동일성(identity) 보장
1
2
3
4
Member a = em.find(Member.class, "m1");
Member b = em.find(Member.class, "m1");
System.out.println(a == b); // true, 1차 캐시를 통해 반복 가능한 읽기 등급의 트랜잭션 격리 수준을 애플리케이션 차원에서 제공한다.
트랜잭션을 지원하는 쓰기 지연
1
2
3
4
5
6
7
8
9
EmtityManager em = emf.createEntiryManager();
EntityTransaction transaction = em.getTransaction();
transaction.begin(); // 트랜잭션 시작
em.persist(A); // 쓰기 지연 SQL 저장소에 적재, 1차 캐시에 저장
em.persist(B); // 쓰기 지연 SQL 저장소에 적재, 1차 캐시에 저장
transaction.commit(); // 트랜잭션 커밋, 쓰기 지연 SQL 저장소에 적재된 SQL을 flush 하여 DB에 INSERT SQL을 날리게 된다.
쓰기 지연을 통해 버퍼링을 사용할 수 있게 된다.
hibernate batch 옵션을 통해 batch size 조절 가능하고, 이 사이즈만큼 SQL을 모아서 커밋 시 SQL을 날리는 것이 가능해진다.
변경 감지 (Dirty Checking)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
EmtityManager em = emf.createEntiryManager();
EntityTransaction transaction = em.getTransaction();
transaction.begin(); // 트랜잭션 시작
// 영속 엔티티 조회
Member m = em.find(Member.class, "m1");
// 영속 엔티티 데이터 수정
m.setName("kim");
// em.update(m); ??????? 이런 업데이트 명령 코드가 없어도 변경이 수행된다.
transaction.commit();
- JPA는 일단 값이 변경되면 UPDATE 쿼리가 날라간다고 생각하면 된다.
플러시
- 변경을 감지하여 쓰기 지연 SQL 저장소에 등록된 쿼리를 데이터베이스에 전송한다.
- 플러시하는 방법
- 직접 호출 :
em.flush()
- 자동 호출
- 트랜잭션 커밋
- JPQL 쿼리 실행 : 예를 들어 SELECT 쿼리를 날렸을 때, 이전에 추가한 객체의 반영을 위해 이렇게 구성됨.
- 직접 호출 :
- 플러시를 한다고 1차 캐시가 다 날라가는 것은 아니다. 쓰기 지연 SQL 저장소에 적재되어 있는 쿼리만 DB에 반영한다.
- 즉, 영속성 컨텍스트를 비우지 않고, 변경 내용만 동기화하는 것이다.
준영속 상태
- 영속 상태의 엔티티가 영속성 컨텍스트에서 분리된(detached) 상태로 영속성 컨텍스트가 제공하는 기능 사용이 불가하다.
- 상태 변환 방법
em.detach(entity)
: 엔티티를 준영속 상태로 전환em.clear()
: 영속성 컨텍스트를 완전히 초기화em.close()
: 영속성 컨텍스트를 종료
Comments powered by Disqus.