티스토리 뷰
영속성 관리
1. 영속성 컨텍스트
영속성 컨텍스트: 엔티티를 보관하고 관리하는 공간
1.1 영속성 컨텍스트 구조

1.2 엔티티의 생명주기
비영속: 영속성 컨텍스트와 관련없는 상태영속: 영속성 컨텍스트에 저장된 상태준영속: 영속성 컨텍스트에 저장되었다가 분리된 상태삭제: 삭제된 상태
1.3 영속성 컨텍스트의 특징
- 영속성 컨텍스트는 엔티티를 식별자 값으로 구분한다.
- 영속성 컨텍스트에 저장된 엔티티는
flush()가 호출될 때 DB에 반영한다. - J2SE 환경에서는 EntityManager 1개 당 PersistenceContext 1개가 생성된다.
- J2EE 환경에서는 EntityManager n개가 PersistenceContext 1개를 공유한다.
1.4 영속성 컨텍스트가 엔티티를 관리함으로써 얻는 장점
- 1차 캐시
- 동일성 보장
- 트랜잭션을 지원하는 쓰기 지연
- 변경 감지 (dirty checking)
- 지연 로딩
2. 등록, 수정, 삭제, 조회
2.1 등록
과정
- 영속성 컨텍스트 내부의 1차 캐시에 식별자로 구분하여 해당 엔티티를 저장하고 쓰기지연 SQL 저장소에 Insert 쿼리를 저장
flush()호출- 쓰기지연 SQL 저장소에 모아둔 쿼리를 DB에 전달
Member member = new Member();
member.setId("member1");
member.setUsername("이수근");
em.persist(member);
2.2 조회
- 영속 엔티티의 동일성 보장 (
em.find()로 같은 엔티티를 반복해서 조회할 경우 1차 캐시에 있는 동일한 엔티티가 반환)
과정
- 1차 캐시에 해당 식별자 값으로 엔티티를 조회
- 1차 캐시에 없으면 DB에 해당 식별자 값으로 데이터를 조회해서 엔티티를 생성
- 1차 캐시에 해당 엔티티를 저장한 후 영속 상태의 엔티티 반환
Member member = em.find(Member.class, "member1"); // find(엔티티 클래스 타입, 식별자 값)
2.3 수정
- 변경 감지는 영속 상태의 엔티티만 적용 가능
- JPA의 기본 수정 전략은 엔티티의 모든 필드를 업데이트하는 것이다.
- 애플리케이션 로딩 시점에 수정 쿼리를 미리 생성해두고 재사용 가능
- DB에 동일한 쿼리를 보낼 경우 이전에 파싱된 쿼리 재사용 가능
과정
- 영속성 컨텍스트에 엔티티 저장시 최초 상태를 복사한
스냅샷을 같이 저장 - 영속 상태의 엔티티를 수정
flush()호출- 1차 캐시에서 엔티티와 스냅샷을 비교하여 변경되었는지 확인 (dirty checking)
- 변경된 엔티티에 맞게 Update 쿼리를 생성 후 쓰기지연 SQL 저장소에 저장
- 쓰기지연 SQL 저장소에 모아둔 쿼리를 DB에 전달
Member member = em.find(Member.class, "member1");
member.setUsername("김병만");
2.4 삭제
과정
- 1차 캐시에서 해당 엔티티를 제거
- 쓰기지연 SQL 저장소에 Delete 쿼리 저장
- flush() 호출
- 쓰기지연 SQL 저장소에 모아둔 쿼리를 DB에 전달
Member member = em.find(Member.class, "member1");
em.remove(member);
3. 플러시
flush() : 영속성 컨텍스트의 변경 내용을 DB에 반영한다.
3.1 플러시 과정
- 변경 감지
- 쓰기지연 SQL 저장소에 모아둔 쿼리를 DB에 전달
3.2 플러시 호출 방법
em.flush()로 직접 호출트랜잭션 커밋시 자동 호출JPQL쿼리 실행시 자동 호출
3.3 플러시 모드 옵션
FlushModeType.AUTO: 커밋이나 쿼리를 실행할 때 플러시 (기본값)FlushModeType.COMMIT: 커밋할 때만 플러시
4. 준영속
4.1 영속 상태 엔티티를 준영속 상태로 만드는 방법
em.detach(entity): 특정 엔티티만 준영속 상태로 전환 (in. 1차 캐시 + 쓰기지연 SQL 저장소)em.clear(): 영속성 컨텍스트를 초기화em.close(): 영속성 컨텍스트를 종료
4.2 준영속 상태의 특징
- 영속성 컨텍스트가 관리하지 않는다.
- 식별자 값을 갖고 있다.
- 지연 로딩을 할 수 없다.
4.3 병합
em.merge(entity): 준영속 상태의 엔티티를 다시 새로운 영속 상태의 엔티티로 반환
Member mergeMember = em.merge(member);
병합 vs 변경 감지
병합의 과정

1. 준영속 상태의 엔티티 식별자로 1차 캐시에 `조회`
2. 1차 캐시에 없으면 DB에서 조회
3. DB에서 조회한 실제 엔티티를 1차캐시에 저장
4. 준영속 상태의 엔티티의 모든 데이터를 실제 엔티티에 병합
5. 실제 엔티티를 반환
6. flush()를 하여 변경 감지 후 DB에 반영
병합을 사용하면 안되는 이유
1. 병합하는 과정에서 준영속 상태의 엔티티의 데이터를 복사하기 때문에 실수로 필드 값을 null로 지정하면 DB에 null로 반영된다.
2. DB에 해당 식별자를 갖는 엔티티를 가져오기위해 조회(select) 쿼리가 나간다.
3. 준영속 상태의 엔티티와 실제 엔티티는 동일성(==)을 보장하지 않는다.
비영속 상태의 병합
1. 비영속 상태의 엔티티 식별자로 1차 캐시에 조회
2. 1차 캐시에 없으면 DB에 조회
3. DB에 없으면 새로운 엔티티를 생성해서 1차 캐시에 저장
4. 비영속 상태의 엔티티의 모든 데이터를 새로운 엔티티에 병합
5. 새로운 엔티티 반환
6. flush()를 하여 변경 감지 후 DB에 반영
따라서, 병합은 비영속, 준영속을 구분하지 않고 수행된다.
Reference
- 자바 ORM 표준 JPA 프로그래밍 [김영한]
'backend > jpa' 카테고리의 다른 글
| Ch.7 고급 매핑 (0) | 2023.05.03 |
|---|---|
| Ch.6 다양한 연관관계 매핑 (0) | 2023.05.03 |
| Ch.5 연관관계 매핑 (0) | 2023.05.03 |
| Ch.4 엔티티 매핑 (1) | 2023.05.03 |
| Ch1. JPA 기본 (0) | 2023.05.03 |
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- 백준 경사로
- 최대 공약수
- 백준 14890
- 백준 치킨 배달
- Unpacking
- 백준 15684
- set메서드
- *args
- 백준 사다리 조작
- sorted
- 백준 감시
- 백준 15685
- Python
- 백준 14891
- list method
- Split
- setmethod
- 파이썬
- 백준 15686
- 최소 공배수
- 리스트 메서드
- 백준 톱니바퀴
- JOIN
- 백준
- 백준 인구 이동
- 백준 16234
- 백준 15683
- **kwargs
- tuple method
- 백준 드래곤 커브
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | |||
| 5 | 6 | 7 | 8 | 9 | 10 | 11 |
| 12 | 13 | 14 | 15 | 16 | 17 | 18 |
| 19 | 20 | 21 | 22 | 23 | 24 | 25 |
| 26 | 27 | 28 | 29 | 30 |
글 보관함