EntityManager
- EntityManager는 데이터베이스 연결이 꼭 필요한 시점까지 커넥션을 얻지 않는다.
- 트랜잭션을 시작할 때 커넥션을 획득한다.(@Transactional이 없으면 EntityManager를 관리하지 못한다.)
- 하이버네이트를 포함한 JPA구현체들은 EntityManagerFactory를 생성할 때 커넥션 풀도 만든다.
- 스프링 부트에서는 필터(OSIV) - DS - C - S - R - DB 순으로 처리된다.
필터(OSIV) - DS - C 에서는 트랜잭션이 ReadOnly이다.
S - R - DB 단계에서는 읽고 쓰기가 가능하다.
레이지 로딩 사용하려고 필터단계에서 트랜잭션이 시작된다.
영속성 컨텍스트(Persistence context)
- 엔티티를 영구 저장하는 환경
- 논리적인 개념에 가깝다.
- 영속성 컨텍스트는 EntityManager를 생성할 때 하나 만들어진다. 그리고 엔티티 메니저는 영속성 컨텍스트에 접근할 수 있고, 영속성 컨텍스트를 관리할 수 있다.
영속성 컨텍스트 특징
- 영속성 컨텍스트와 식별자 값. : 영속성 컨텍스트는 엔티티를 식별자 값으로 구분한다. 영속상태는 식별자 값이 반드시 있어야 한다.
- 영속성 컨텍스트와 데이터 베이스 저장 : JPA는 보통 트랜잭션이 커밋하는 순간 영속성 컨텍스트에 새로 저장된 엔티티를 데이터베이스에 반영한다.이를 flush라고 한다.
- 영속성 컨텍스트가 엔티티를 관리할 때의 장점 : 1차 캐시, 동일성 보장, 트랜잭션을 지원하는 쓰기 지연, 변경감지, 지연 로딩
엔티티 조회, 입력
영속성 컨텍스트는 내부에 캐시를 가지고 있는데, 이를 1차 캐시라 한다. 영속상태의 엔티티는 모두 이곳에 저장된다.
1차 캐시의 키는 식별자 값이다. 이미 1차캐시에 있을 경우 db에서 조회하지 않고 캐시에서 조회하게 된다.
ex> em.persist(member); 가 호출될 경우 1차 캐시에 저장된다.
ID를 자동생성으로 셋팅하면 DB에 insert가 먼저 일어나고 키를 얻어온다. 자동생성 하지 않으면 DB에 INSET하지 않고 ID를 가지고 1차캐시에 저장된다.
jpa는 영속성 컨텍스트에 보관할 때 최초 상태를 복사해서 저장해둔다. 이를 스냅샷이라 한다. 그리고 플러시 시점에 스냅샷과 엔티티를 배고해 변경된 엔티티를 찾는다.
변경된 엔티티가 있으면 수정 쿼리를 생성해서 쓰기 지연 sql저장소에 보낸다.
쓰기 지연 저장소의 sql을 데이터베이스 보낸다.
변경관리는 영속성 컨텍스트가 관리하는 영속 상태의 엔티티에만 적용된다.
ID를 자동생성으로 셋팅하면 DB에 insert가 먼저 일어나고 키를 얻어온다. 자동생성 하지 않으면 DB에 INSET하지 않고 ID를 가지고 1차캐시에 저장된다.
엔티티 수정
엔티티가 수정된 것을 감지하여 db내용을 수정하는 것을 변경감지라한다.jpa는 영속성 컨텍스트에 보관할 때 최초 상태를 복사해서 저장해둔다. 이를 스냅샷이라 한다. 그리고 플러시 시점에 스냅샷과 엔티티를 배고해 변경된 엔티티를 찾는다.
변경된 엔티티가 있으면 수정 쿼리를 생성해서 쓰기 지연 sql저장소에 보낸다.
쓰기 지연 저장소의 sql을 데이터베이스 보낸다.
변경관리는 영속성 컨텍스트가 관리하는 영속 상태의 엔티티에만 적용된다.
엔티티 생명주기
- 비영속(new/transient) : 영속성 컨텍스트와 전혀 관계가 없는 상태
- 영속(managed) : 영속성 컨텍스트에 저장된 상태
- 준영속(detached) : 영속성 컨텍스트에 저장되었다가 분리된 상태
- 삭제(removed) : 삭제된 상태
User user = new User();
위의 user객체는 비영속 상태다.
EntityManager를 통해 엔티티를 영속성 컨텍스트에 저장할 경우 영속 상태가 된다.
영속성 컨텍스트에 위해 관리되는 상태를 영속상태라 한다.
영속상태라는 것은 영속성 컨텍스트에 의해 관리된다는 것을 의미한다.
조회된 엔티티도 영속성 컨텍스트가 관리하는 영속 상태다.
EntityManager가 관리하던 엔티티를 더이상 관리하지 않으면 준영속상태가 된다.
em.detach()를 호출하면 된다. 혹은 em.close()를 호출해서 영속성 컨텍스트를 닫거나 em.clear()를
해서 영속성 컨텍스트가 초기화 해도 영속성 컨텍스가 관리하던 엔티티가 준영속 상태가 된다.
em.detach(user);
삭제는 em.remove(user); 를 이용해서 삭제할 경우이다.
준영속
영속 상태의 엔티티를 준영속 상태로 만드는 방법- em.detach(entity) : 특정 엔티티를 준영속 상태로 전환한다. 1차 캐시부터 쓰기 지연 sql저장소까지 해당 엔티티를 관리하기 위한 모든 정보가 제거된다.
- em.clear() : 영속성 컨텍스트를 초기화 한다.
- em.close() : 영속성 컨텍스트를 종료한다.
준영속 상태의 특징
- 거의 비영속 상태에 가깝다.- 식별자 값을 가지고 있다.
- 지연 로딩을 할 수 없다.
merge()를 통해 병합할 수 있다.
준영속 상태의 엔티티를 다시 영속상태로 변경할 경우 merge()를 사용한다.
ex: User user = em.merge(user);
영속 엔티티의 동일성 보장
같은 id의 값을 가진 엔티티를 조회하면 == 를 이용했을 경우 참이 나온다. 이를 동일성이라한다. 이는 실제 인스턴스가 같다는 것을 의미한다.트랜잭션 지연쓰기
ex> em.persist(user1); em.persist(user2); 와 같이 여러번 영속성을 부여한 다음 트랜잭션을 커밋할 때 한꺼번에 sql이 실행된다. 이를 트랜잭션을 지원하는 쓰기 지연이라고 말한다.이를 flush라고 한다.
모아둔 쿼리를 한번에 전달해서 성능을 최적화 할 수 있다.
0 개의 댓글:
댓글 쓰기