3장 영속성 관리
∘ 엔티티 매니저 : 엔티티를 저장, 수정, 삭제, 조회하는 등 엔티티와 관련된 모든 일을 처리함
∘ '엔티티 매니저 = 엔티티를 저장하는 가상의 데이터베이스'라고 생각하면 됨
3.1 엔티티 매니저 팩토리와 엔티티 매니저
∘ 엔티티 매니저 팩토리 생성 코드
EntityManagerFactory emf = Persistence.createEntityManagerFactory("jpabook");
∘ 엔티티 매니저 팩토리에서 엔티티 매니저 생성
EntityManager em = emf.createEntityManager();
∘ 엔티티 매니저 팩토리 : 엔티티 매니저를 만드는 공장
- 엔티티 매니저 팩토리를 생성하는 데 드는 비용이 크기 때문에 애플리케이션 당 1개만 만들어서 공유해서 사용
- 엔티티 매니저 팩토리는 여러 스레드가 동시에 접근해도 안전함. 서로 다른 스레드 간에 공유해도 됨.
↔ 엔티티 매니저는 여러 스레드가 동시에 접근하면 동시성 문제 발생함. 스레드 간에 공유하면 안 됨.
∘ 엔티티 매니저는 데이터베이스 연결이 꼭 필요한 시점까지 커넥션을 얻지 않음
3.2 영속성 컨텍스트란?
∘ 영속성 컨텍스트(persistence context) : 엔티티를 영구 저장하는 환경
- 엔티티 매니저를 생성할 때 하나 만들어짐
- 엔티티 매니저를 통해 접근, 관리
∘ 엔티티 매니저로 엔티티를 저장하거나 조회하면 엔티티 매니저는 영속성 컨텍스트에 엔티티를 보관하고 관리
∘ persist() : 엔티티 매니저를 사용해서 회원 엔티티를 영속성 컨텍스트에 저장
3.3 엔티티의 생명주기
∘ 비영속(new/transient) : 영속성 컨텍스트와 전혀 관계가 없는 상태
- 엔티티 생성 후, 저장 전
∘ 영속(managed) : 영속성 컨텍스트에 저장된 상태
- 영속성 컨텍스트가 관리하는 엔티티
- em.persist()
- em.find()
∘ 준영속(detached) : 영속성 컨텍스트에 저장되었다가 분리된 상태
- 영속 상태의 엔티티를 영속성 컨텍스트가 관리하지 않으면 준영속 상태가 됨
- em.detach()
∘ 삭제(removed) : 삭제된 상태
- 엔티티를 영속성 컨텍스트와 데이터베이스에서 삭제
- em.remove()
3.4 영속성 컨텍스트의 특징
∘ 영속성 컨텍스트와 식별자 값
- 엔티티를 식별자 값(@ID로 테이블의 기본 키와 매핑한 값)으로 구분
⇒ 영속 상태는 식별자 값이 반드시 있어야 함
∘ 영속성 컨텍스트와 데이터베이스 저장
- JPA는 보통 트랜잭션을 커밋하는 순간 영속성 컨텍스트에 새로 저장된 엔티티를 데이터베이스에 반영
∘ 영속성 컨텍스트가 엔티티를 관리할 때의 장점
- 1차 캐시
- 동일성 보장
- 트랜잭션을 지원하는 쓰기 지연
- 변경 감지
- 지연 로딩
3.4.1 엔티티 조회
∘ 1차 캐시 : 영속성 컨텍스트가 내부에 가지고 있는 캐시. 모든 영속 상태의 엔티티가 저장되는 곳.
- 키는 @Id로 매핑한 식별자
- 식별자 값은 데이터베이스 기본 키와 매핑되어 있음
∘ em.find()를 호출하면 먼저 1차 캐시에서 식별자 값으로 엔티티를 찾음. 1차 캐시에 없으면 데이터베이스에서 조회.
1차 캐시에서 조회
∘ em.find()로 엔티티 찾음 → 엔티티가 있으면 1차 캐시에서 엔티티 조회
데이터베이스에서 조회
∘ em.find() 호출했는데 엔티티가 1차 캐시에 없음 → 엔티티 매니저가 데이터베이스를 조회해서 엔티티 생성 → 1차 캐시에 저장 → 영속 상태의 엔티티 반환
영속 엔티티의 동일성 보장
∘ 같은 식별자로 조회한 인스턴스는 동일한 인스턴스
∘ 영속성 컨텍스트는 성능상 이점과 엔티티의 동일성 보장
3.4.2 엔티티 등록
∘ 쓰기 지연 : 엔티티 매니저는 트랜잭션을 커밋하기 전까지 데이터베이스에 엔티티를 저장하지 않고 내부 쿼리 저장소에 INSERT SQL을 모아두고 있다가 트랜잭션을 커밋할 때 모아둔 쿼리를 데이터베이스에 보냄
∘ 트랜잭션 커밋 commit() → 영속성 컨텍스트를 플러시 → 실제 데이터베이스에 트랜잭션을 커밋
트랜잭션을 지원하는 쓰기 지연이 가능한 이유
∘ 트랜잭션을 커밋하기 전까지 쿼리가 반영되지 않음
3.4.3 엔티티 수정
SQL 수정 쿼리의 문제점
∘ 발생할 수 있는 모든 상황에 대한 수정 쿼리를 추가하다보면 수정 쿼리의 개수가 많아지고, 비즈니스 로직을 분석하기 위해 SQL을 계속 확인해야 함 ⇒ 비즈니스 로직이 SQL에 의존하게 됨
변경 감지
∘ JPA로 엔티티를 수정하려면 단순히 엔티티를 조회해서 데이터만 변경하면 됨
∘ 변경 감지(dirty checking) : 엔티티의 변경사항을 데이터베이스에 자동으로 반영하는 기능
∘ JPA는 엔티티를 영속성 컨텍스트에 보관할 때 최초 상태를 복사해서 저장해둠 (스냅샷)
→ 플러시 시점에 스냅샷과 엔티티를 비교해서 변경된 엔티티를 찾음
∘ 영속성 컨텍스트가 관리하는 영속 상태의 엔티티에만 적용됨
∘ JPA의 기본 전략은 변경된 부분에 대해서만 수정 쿼리를 생성하지 않고, 엔티티의 모든 필드를 업데이트
∘ 필드가 많거나 저장되는 내용이 너무 크면 수정된 데이터만 사용해서 동적으로 UPDATE SQL을 생성하도록 하면 됨
3.4.4 엔티티 삭제
∘ 엔티티 삭제하려면 삭제하려는 엔티티 조회부터 해야 됨
∘ em.remove()
∘ em.remove()를 호출하면 해당 엔티티는 영속성 컨텍스트에서 제거됨 (실제 데이터베이스에서 삭제되는 건 트랜잭션 커밋, 플러시 후)
3.5 플러시
∘ flush()
∘ 플러시 : 영속성 컨텍스트의 변경 내용을 데이터베이스에 반영
∘ 영속성 컨텍스트를 플러시하는 방법
- 직접 호출
- 트랜잭션 커밋 시 플러시 자동 호출
- JPQL 쿼리 실행 시 플러시 자동 호출
3.5.1 플러시 모드 옵션
∘ FlushModeType.AUTO : 커밋이나 쿼리를 실행할 때 플러시 (기본값)
∘ FlushModeType.COMMIT : 커밋할 때만 플러시
∘ 동기화 기능
3.6 준영속
∘ 준영속 상태 : 영속성 컨텍스트가 관리하는 영속 상태의 엔티티가 영속성 컨텍스트에서 분리된 상태
∘ 준영속 상태의 엔티티는 영속성 컨텍스트가 제공하는 기능을 사용할 수 없음
∘ 영속 상태의 엔티티를 준영속 상태로 만드는 방법
- em.detach(entity)
- em.clear()
- em.close()
3.6.1 엔티티를 준영속 상태로 전환: detach()
∘ em.detach(entity)를 호출하면 해당 엔티티를 관리하기 위한 모든 정보가 제거됨
∘ 준영속 상태 : 영속 상태였다가 더는 영속성 컨텍스트가 관리하지 않는 상태
3.6.2 영속성 컨텍스트 초기화: clear()
∘ em.clear() : 영속성 컨텍스트를 초기화해서 해당 영속성 컨텍스트의 모든 엔티티를 준영속 상태로 만듦
3.6.3 영속성 컨텍스트 종료: close()
∘ 영속성 컨텍스트를 종료하면 해당 영속성 컨텍스트의 영속 상태의 엔티티가 모두 준영속 상태가 됨
3.6.4 준영속 상태의 특징
∘ 거의 비영속 상태에 가까움
∘ 식별자 값을 가지고 있음
∘ 지연 로딩을 할 수 없음
- 지연 로딩(LAZY LOADING) : 실제 객체 대신 프록시 객체를 로딩해두었다가 해당 객체를 실제로 사용할 때 영속성 컨텍스트를 통해 데이터를 불러오는 방법. 영속 상태일 때 사용.
3.6.5 병합: merge()
∘ 준영속 상태의 엔티티를 다시 영속 상태로 변경할 때 병합 사용
∘ merge()는 준영속 상태의 엔티티로부터 얻은 정보로 새로운 영속 상태의 엔티티를 반환
준영속 병합
비영속 병합
3.7 정리
∘ 엔티티 매니저는 엔티티 매니저 팩토리가 생성
∘ 엔티티 매니저가 만들어지면 그 내부에 영속성 컨텍스트가 만들어짐
∘ 영속성 컨텍스트는 엔티티 매니저를 통해서 접근
∘ 영속성 컨텍스트는 1차 캐시, 쓰기 지연 등의 기능을 제공
∘ 일반적으로 트랜잭션을 커밋할 때 영속성 컨텍스트가 플러시됨
∘ 영속, 더 이상 관리하지 않으면 준영속
∘ 준영속 상태의 엔티티는 영속성 컨텍스트의 기능을 사용할 수 없음
'Back-End > 자바 ORM 표준 JPA 프로그래밍' 카테고리의 다른 글
[JPA] 자바 ORM 표준 JPA 프로그래밍_7장 (0) | 2023.06.24 |
---|---|
[JPA] 자바 ORM 표준 JPA 프로그래밍_6장 (0) | 2023.06.20 |
[JPA] 자바 ORM 표준 JPA 프로그래밍_5장 (0) | 2023.06.05 |
[JPA] 자바 ORM 표준 JPA 프로그래밍_4장 (0) | 2023.05.29 |
[JPA] 자바 ORM 표준 JPA 프로그래밍_1장 (0) | 2023.05.20 |