[JPA] 스터디 1주차 - 3장 영속성 관리
JPA 스터디 : 3장 영속성 관리
1주차 영속성 관리와 엔티티 매핑
- 3장 영속성 관리 : 90p-119p
- 4장 엔티티 매핑 : 122p-153p
- 5장 연관관계 매핑 기초 : 164p-195p
3장. 영속성 관리
- 엔티티 매니저는 엔티티를 저장, 수정, 삭제, 조회하는 등 엔티티와 관련된 모든 일 처리
3.1 엔티티 매니저 팩토리 & 엔티티 매니저
DB 하나만 사용하는 애플리케이션 => 일반적으로 EntityManagerFactory 하나 생성
// entity manager factory 생성
EntityManagerFactory emf = Persistence.createEntityManagerFactory("jpabook");
// entity manager 생성
EntityManager em = emf.createEntityManager();
엔티티 매니저 팩토리
- 여러 스레드가 동시에 접근해도 안전 : 서로 다른 스레드 간 공유 가능
- cf)
엔티티 매니저
: 여러 스레드 동시 접근 시 문제 발생 ~> 스레드 간 절대 공유 ❌ - Connection Pool : Hibernate 등 JPA 구현체들은 EntityMangerFactory 생성할 때 같이 생성
엔티티 매니저
- 엔티티 매니저 팩토리 통해 생성
- 동시성 문제 O : 스레드 간 공유 X
- 데이터베이스 연결이 꼭 필요한 시점까지 커넥션 획득 X
- eg) 트랜잭션 시작 시 커넥션 획득
3.2 영속성 컨텍스트?
엔티티를 영구 저장하는 환경
- 엔티티 매니저를 생성할 때 하나 생성됨
3.3 엔티티의 생명주기
- 비영속(new/transient) : 영속성 컨텍스트와 무관 상태
- 영속(managed) : 영속성 컨텍스트에 저장된 상태
- 준영속(detached) : 영속성 컨텍스트에 저장되었다가 분리된 상태
- 삭제(removed) : 삭제 상태
비영속
- 엔티티 객체 생성 ~~ 영속성 컨텍스트, 데이터베이스와 무관
영속
- 엔티티 매니저 통해 엔티티를 영속성 컨텍스트에 저장
- 영속성 컨텍스트가 관리하는 엔티티 상태
em.persist(member)
: 엔티티 매니저를 사용해서 회원 엔티티를 영속성 컨텍스트에 저장em.find()
, JPQL 사용해 조회한 엔티티
준영속
- 영속 상태 엔티티를 영속성 컨텍스트가 관리 하지 않는 상태
em.detach()
,em.close()
,em.clear()
삭제
- 영속성 컨텍스트, 데이터베이스에서 삭제
em.remove(member)
3.4 영속성 컨텍스트 특징
식별자 값
- 영속성 컨텍스트는 엔티티를
식별자 값
(@Id)으로 구분 - 영속 상태는 식별자 값이 반드시 있어야 함
- 없을 경우, 예외 발생
DB 저장
- 영속성 컨텍스트에서 관리하는 엔티티는
플러시
하는 순간 DB에 저장됨
장점
- 1차 캐시
- 동일성 보장
- 트랜잭션을 지원하는 쓰기 지연
- 변경 감지
- 지연 로딩
엔티티 조회
- 1차 캐시 : 영속성 컨텍스트가 내부에 가지고 있는 캐시
- 먼저 1차 캐시에서 조회 -> 없을 경우 DB에서 조회 -> 1차 캐시에 저장, 영속 상태 엔티티 반환
- 영속성 컨텍스트는 1차 캐시에 있는 같은 엔티티 인스턴스를 반환 : 영속 엔티티의 동일성 보장
- 1차 캐시를 통해 REPEATABLE READ 등급의 트랜잭션 격리 수준을 DB가 아닌 애플리케이션 수준에서 제공
엔티티 등록
- 트랜잭션을 커밋할 때 모아둔 쿼리를 DB에 보내는데 이것을
트랜잭션을 지원하는 쓰기 지연
엔티티 수정
- 변경 감지(dirty checking)
- 엔티티의 변경사항을 데이터 베이스에 자동으로 반영하는 기능
- 엔티티가 영속성 컨텍스트에 저장될 때 최초의 상태 : 스냅샷
- flush 할 때 스냅샷과 엔티티를 비교 -> 변경 시 update 구문 쓰기 지연 sql 저장소에 보냄
- 영속성 컨텍스트가 관리하는 영속 상태의 엔티티에만 적용됨
- JPA의 기본 전략 : 엔티티의 모든 필드 업데이트
- 단점 : 데이터 전송량 증가
- 장점
- 모든 필드 수정 시 수정 쿼리 미리 생성 후 재사용 가능
- DB에서도 한 번 파싱된 쿼리 재사용 가능
@org.hibernate.annotations.DynamicUpdate
통해 동적 Update SQL 생성 전략 선택 가능- 상황마다 다르나 컬럼이 대략 30개 이상 되면 정적 수정 쿼리보다 동적 수정 쿼리가 빠르다고 함 —> 단, 테스트 해봐야!
엔티티 삭제
em.remove(member)
: 호출하는 순간 영속성 컨텍스트에서 삭제됨
3.5 플러시
영속성 컨텍스트의 변경 내용을 DB에 반영
- 변경 감지 동작 -> 영속성 컨텍스트에 있는 모든 엔티티를 스냅샷과 비교. 수정된 엔티티 찾음 -> 수정된 엔티티의 수정 쿼리 생성. 쓰기 지연 SQL 저장소에 등록
- 쓰기 지연 SQL 저장소의 쿼리를 DB에 전송
플러시 방법 3가지
- em.flush() 직접 호출
- 트랜잭션 커밋 시 플러시 자동 호출
- JPQL 쿼리 실행 시 플러시 자동 호출
- JPQL, Criteria 등의 객체지향 쿼리 호출 시
- JPQL은 sql로 변환되어 DB에서 엔티티 조회. 쿼리 실행 전에 영속성 컨텍스트의 변경 내용을 DB에 반영해야 함.
플러시 모드 옵션
javax.persistence.FlushModeType
- FlushModeType.AUTO : 커밋이나 쿼리 실행 시 플러시 (기본 설정)
- FlushModeType.COMMIT : 커밋할 때만 플러시
3.6 준영속
엔티티가 영속 상태의 엔티티가 영속성 컨텍스트에서 분리된 상태
- 준영속 상태의 엔티티는 영속성 컨텍스트 제공 기능 사용 불가
- 준영속 상태 만드는 법 3가지
- em.detach(entity) : 특정 엔티티만 준영속 상태 전환
- em.clear() : 영속성 컨텍스트 초기화
- em.close() : 영속성 컨텍스트 종료
준영속 상태 특징
- 거의 비영속 상태에 가까움
- 식별자 값 소유
- 지연 로딩 불가
참조
- 자바 ORM 표준 JPA 프로그래밍, 김영한 지음