엔티티매니저 팩토리, 엔티티매니저, 영속성 컨텍스트
Persistence란?
정의: Entity가 영구적으로 저장될수 있도록 제공해주는 환경을 의미
EntityFactory 와 EntityManager
EntiyManagerFactory 는 EntityManager를 생성을 담당한다. 애플리케이션 실행동안 한번만 생성되는 중량 객체이며, EntityManager가 통신하는 데이터 커넥션 풀을 만든다.
EntityManager는 단일 데이터베이스 연결을 나타내는 경량객체이다. EntityManager는 데이터베이스와 연결하여 트랜잭션단위의 범위를 가진다.
전체 과정은 대략 이렇다.
EntityManagerFactory가 -> EntityManager (= PersistenceContext)
애플리케이션이 실행될때, EntityManagerFactory가 생성된다. EntityManagerFactory가 생성하는 시점에 데이터베이스 커넥션 풀이 생성된다. 생성된 커넥션 풀을 가지고 DB에 접근할때마다 커넥션을 이용해 DB에 접근이 가능하다.
이제 사용자가 원하는 정보를 꺼내오는 상황을 생각해보자 EntityManagerFactory는 클라이언트 요청에의해 EntityManager를 생성해준다.
EntityManager가 생성되면 PersistenceContext가 생성된다. PersistenceContext는 트랜잭션 동안 엔티티 개체에대한 변경 사항을 추적하여 관리하는 역할을 제공한다. PersistenceContext 트랜잭션 중에 엔티티와 관련된 모든 변경사항들을 추적하고 트랜잭션이 커밋될 때 변경사항을 커넥션 풀을 이용해 데이터베이스에 동기화 한다. 이는 데이터의 일관성과 무결성을 보장하는데 도움을 준다. 따라서 PersistenceContext는 EntityManager에게 엔티티를 관리하는 기능을 제공해준다.
+추가 엔티티매니저 역할 : 커넥션관리
영속성 컨텍스트
정의: 엔티티를 영구 저장하는 환경
엔티티(Entity)를 저장하고 관리하는 저장소 개념 영속성 컨텍스트는 엔티티 매니저를 통해 엔티티에 접근가능하다. 엔티티는 식별자(@Id)로 식별하기때문에 반드시 존재해야한다.
엔티티의 생명주기
- 비영속
- 영속컨텍스트를 사용하기 전 객체
- 영속 (persist / find)
- 비영속 객체를 컨텍스트에 넣어진 상태
- 아직 DB에 저장되지 않은상태
- 준영속 (detach / clear)
- 엔티티를 영속성컨텍스트에서 제거
- 영속성 컨테스트가 관리하지 않는 상태
- 삭제 (remove)
영속성 컨텍스트 이점
- 1차 캐시
Member member=new Member(); member.setId("member1"); member.setUsername("회원1"); // 엔티티를 1차 캐시에 저장 em.persistence(member);
1차 캐시 조회와 DB에서 조회 예제코드
Member member=new Member(); member.setId("member1"); member.setUsername("회원1"); em.persistence(member); // 1차 캐시에서 바로 조회가 가능한 경우 Member findMember=em.find(Member.class,"member1"); // 1차 캐시를 먼저 탐색하고 존재하지 않으면 DB에서 해당 객체를 찾아서 반환해준다. Member findMember2=em.find(Member.class,"member2");
-
동일성 보장
1차 캐시에서 조회가능한 객체를 애플리케이션 차원에서 지원
-
변경감지 (스냅샷)
jpa에선 데이터를 조회하고 수정하기만하여도 이를 감지해 준다.
EntityManager em = emf.createEntityManager(); EntityTransaction transaction = em.getTransaction(); transaction.begin(); // [트랜잭션] 시작 // 영속 엔티티 조회 Member memberA = em.find(Member.class, "memberA"); // 영속 엔티티 데이터 수정 memberA.setUsername("hi"); memberA.setAge(10); //em.update(member) 이런 코드가 있어야 하지 않을까? transaction.commit(); // [트랜잭션] 커밋
-
지연로딩
JPA는 entity값들을 변경한다고해서 바로 DB에 반영하지 않는다. 쓰기지연SQL저장소에 바뀐 entity 쿼리문을 보관하고 엔티티매니저의 flush() 나 트랜잭션 commit 명령어를 통해 한번에 보내지게 된다.
-
플러시
영속성 컨텍스트의 변경내용을 데이터 베이스에 반영
변경 감지 -> 수정된 엔티티 쓰기 지연 SQL 저장소에 등록 ->쓰기지연 SQL 저장소의 쿼리를 데이터 베이스에 전송
em.flush(); // comit까지 기다리지 않고 쿼리가 바로 DB에 반영
주의! ‘플러시’는 영속성 컨테스트를 비우는 것이 아니라 변경내용을 데이터 베이스에 동기화