
영속성 컨텍스트와 엔티티 매니저를 공부해야 하는 이유
JPA 는 자바 표준 ORM 기술이고 JPA 의 핵심 개념이 영속성 컨텍스트, 엔티티 매니저이기 때문이에요.
영속성 컨텍스트, 엔티티 매니저를 이해하지 못하면 JPA 의 장점을 활용할 수 없기에 학습할 필요가 있어요.
효율적인 ORM 을 위해서는 영속성 컨텍스트와 엔티티 매니저를 공부해야 해요.
영속성 컨텍스트에 대한 이해가 부족하다면, 동일한 데이터를 반복적으로 조회하는 쿼리를 실행하는 경우처럼 SQL 을 직접 사용해 개발하는 경우보다 비효율적일 수 있어요.
영속성 컨텍스트의 특징을 이해하고 사용해야 DB 접근을 최소화하여 DB 가 받는 부하를 줄일 수 있어요.
ORM
Object Relational Mapping 의 약자로, 객체를 DB Table 과 매핑해주는 기술이에요.
기존 ODBC, JDBC 를 한 번 더 wrapping 한 기술로, DB 연결을 더 쉽게 해주는 기술이에요.
JPA 의 요소 5가지
1. Entity
DB 에 mapping 될 객체를 의미해요.

2. Entity Manager
Entity 를 관리하는 객체를 의미해요.

3. Entity Manager Factory
Entity Manager 를 생성하는 객체를 의미해요.

4. Persistence Context
Entity 를 효율적으로 관리하는 공간을 의미해요.

5. Persistence Unit
DB 연결을 위한 설정을 의미해요.
application.yml 을 예시로 들 수 있어요.
Entity 의 상태 4가지
Entity 는 영속성 컨텍스트를 기준으로 4가지의 상태를 가져요.
1. 비영속 상태 (New / Transient)
객체는 생성되었지만, 영속성 컨텍스트에서 관리되지 않고 있는 상태를 의미해요.
DB, JPA 와 아무런 관계가 없어요.
2. 영속 상태 (Managed)
Entity 가 영속성 컨텍스트에 저장되어 관리되고 있는 상태를 의미해요.
영속성 컨텍스트의 특징인 1차 캐시, 쓰기 지연, 변경 감지의 대상이 돼요.
3. 준영속 상태 (Detached)
이전에는 영속 상태였으나 현재는 영속성 컨텍스트에서 분리된 상태를 의미해요.
영속성 컨텍스트가 닫히면 그 안에 있던 영속 객체는 준영속 상태가 돼요.
4. 삭제 상태 (Removed)
영속성 컨텍스트에서 관리되고 있으나 삭제하기로 표시된 상태를 의미해요.
다음 flush 작업 때 DELETE 쿼리를 쓰기 지연 저장소에 추가하여 전송해요.
엔티티 매니저
엔티티 매니저는 메서드를 통해 영속성 컨텍스트 내부 Entity 의 상태를 변경하는 작업을 수행해요.
이 과정을 통해 애플리케이션 서버와 데이터베이스 사이를 연결해요.

엔티티 매니저의 메서드
persist(entity)영속 상태로 전환해요.
detach(entity)준영속 상태로 전환해요.
merge(entity)영속 상태로 전환해요.
remove()삭제 상태로 전환해요.
clear()모든 영속 상태 엔티티를 준영속 상태로 전환해요.
close()영속성 컨텍스트를 닫아, 모든 영속 상태 엔티티를 준영속 상태로 전환해요.
find()영속성 컨텍스트 1차 캐시에 Entity 가 없는 경우 조회 쿼리를 DB 에 전송해요.
flush()쓰기 지연 저장소에 쌓인 쿼리를 DB 에 전송해요.

영속성 컨텍스트의 특징 3가지
1. 1차 캐시
Entity 와 식별자(ID) 가 Map 형태로 저장되어 있는 캐시를 의미해요.
1차 캐시에 Entity 가 있다면, DB 에 조회 쿼리를 보내지 않고도 작업을 수행할 수 있어요.

2. 쓰기 지연 (Write Behind)
Entity 에 대한 쿼리를 DB 에 바로 전송하지 않고 1차 캐시에만 반영해요.
쿼리는 쓰기 지연 저장소에 쌓아두게 되는데, 들어온 쿼리들을 전부 쌓아두는 게 아니라 중간 과정을 생략한 결과 쿼리만을 저장해요.
그리고 flush 작업을 할 때 쓰기 지연 저장소에 있는 쿼리를 DB 에 전송해요.
DB 에 전달되는 쿼리의 수가 줄어 DB 접근 횟수가 줄고, 그 결과 DB 부하를 줄일 수 있어요.

3. 변경 감지 (Dirty Checking)
Entity 가 영속성 컨텍스트에 처음 들어오면 JPA 는 그 상태를 깊은 복사 형태로 스냅샷을 만들어 저장해요.
그리고 flush 작업을 하기 전에 스냅샷과 현재 상태를 비교해요.
상태가 달라졌다면 UPDATE 쿼리를 쓰기 지연 저장소에 추가하여 전송해 변경을 감지해요.
