[JPA] 영속성 컨텍스트
영속성 컨텍스트
엔티티 매니저를 통해서 접근 가능한 논리적인 개념을 의미한다.
→ 엔티티 매니저를 생성하면 내부적으로 PersistenceContext(영속성 컨텍스트) 생성, 스프링 프레임워크 같은 컨테이너 환경에서는 엔티티 매니저와 영속성 컨텍스트가 N:1 관계
외부에서 EntityManager를 주입받는 경우 주입된 EntityManager는 싱글톤
→ 스프링 프레임워크는 프록시 EntityManager를 주입 → 해당 엔티티 매니저를 호출하면 데이터베이스 트랜잭션과 관련된 진짜 EntityManager 호출함으로써 동시성 문제를 해결
엔티티의 생명 주기
- 비영속(new) : 영속성 컨텍스트와 전혀 관계가 없는 새로운 상태
Member member = new Member();
- 영속(managed) : 영속성 컨텍스트에 관리되는 상태
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
em.persist(member); //실제로 DB에 저장되는 것은 아니고 영속성 컨텍스트에서 관리
그럼 데이터베이스에 저장되는 시점은?
플러시(영속성 컨텍스트의 변경 내용을 동기화)가 일어날 때 영속성 컨텍스트의 변경 내용을 데이터베이스에 반영
(영속성 컨텍스트를 비우는 것이 아니라 변경 내용을 동기화 하는 것)
em.persist(E) → 영속성 컨텍스트에 등록할 뿐 쿼리가 나가지 않음.
- 플러시가 발생되는 경우 (쓰기 지연 SQL 저장소에 등록된 쿼리를 반영)
- em.flush() 호출
- 트랜잭션을 커밋하는 경우
- JPQL 쿼리를 실행하는 경우
- 준영속(detached) : 영속성 컨텍스트에 저장되었다가 분리된 상태
em.detach(member); // 특정 엔티티 준영속 상태로 변경
em.clear(); // 영속성 컨텍스트 초기화
em.close(); // 영속성 컨텍스트 종료
- 삭제(remove) : 영속성 컨텍스트에서 삭제된 상태
em.remove(member);
영속성 컨텍스트의 이점
- 동일성을 보장
- 1차 캐시 활용 가능
- 트랜잭션을 지원하는 쓰기 지연
- 변경 감지(Dirty chekcing)
- 지연 로딩이 가능
예를 들어 다음과 같은 코드가 있다고 하자.
Member member = new Member();
member.setId("member1");
member.setUsername("회원1");
em.persist(member); //1차 캐시에 등록
Member findMember = em.find(Member.class, "member1"); //DB가 아닌 1차 캐시에서 조회
해당 member1의 아이디를 가진 멤버를 조회할 때 em.persist를 통해 1차 캐시에 등록을 해놓았으므로 멤버를 DB에서 조회하는 것이 아닌 영속성 컨텍스트에서 조회할 수 있다.
또한 해당 멤버를 여러 번 조회를 하여도 그 인스턴스들은 동일성을 보장하고, 해당 멤버의 이름이 회원1에서 회원2로 변경이 되었을 때 update를 호출하지 않아도 update 쿼리가 나가게 된다.
1차 캐시에 member1이 등록이 될 때 쓰기 지연 저장소에 insert 쿼리를 쌓아두고 트랜잭션이 커밋되는 순간에 해당 저장소에 존재하는 쿼리들이 한 번에 DB에 반영된다는 장점을 가지고 있다.
참고
자바 ORM 표준 JPA 프로그래밍 - 기본편 강의 | 김영한 - 인프런
김영한 | JPA를 처음 접하거나, 실무에서 JPA를 사용하지만 기본 이론이 부족하신 분들이 JPA의 기본 이론을 탄탄하게 학습해서 초보자도 실무에서 자신있게 JPA를 사용할 수 있습니다., 실무에서도
www.inflearn.com