JPA 내부 구조
영속성 컨텍스트
- JPA를 이해하는데 가장 중요한 용어.
- 엔티티를 영구 저장하는 환경 이라는 뜻
- 영속성 컨텍스트는 논리적인 개념이기 때문에 눈에 보이지 않는다
- 엔티티 매니저를 통해 영속성 컨텍스트에 접근한다.
엔티티의 생명 주기
- 비영속 (new / transient) : 영속성 컨텍스트와 전혀 관계가 없는 상태
- 영속 (managed) : 영속성 컨텍스트에 저장된 상태
- 준영속 (detached) : 영속성 컨텍스트에 저장되었다가 분리된 상태
- 삭제 (removed) : 삭제된 상태
비영속
- 생성만 되어있는 상태는 비영속 상태이다.
영속
- 객체를 생성한 후 엔티티매니저를 통해 DB에 넣은 상태
em.persist(manager)
영속성 컨텍스트의 이점
- 1차 캐시
- 동일성(identity) 보장
- 트랜잭션을 지원하는 쓰기 지연 (transactional write-behind)
- 변경 감지(Dirty Checking)
- 지연 로딩(Lazy Loading)
엔티티 조회, 1차 캐시
영속성 컨텍스트 안에는 1차 캐시가 존재한다.
객체를 DB에 넣으면 1차 캐시 안에 Key와 Value를 저장해 놓는다.
이후 조회를 하면 DB까지 가지 않고 먼저 1차캐시안에서 찾아본다. 찾으면 캐시값을 조회해 반환한다.
단, 캐시는 글로벌하게 존재하지 않고 영속성 컨텍스트 안에서만 존재한다.
또한, 트랜잭션 중에만 존재하고 끝나면 사라진다.
만약 데이터베이스에서 조회를 해서 가져와도 1차 캐시에 저장한다.
영속 엔티티의 동일성 보장
1차 캐시로 반복 가능한 읽기(REPEATABLE READ) 등급의 트랜잭션 격리 수준을 데이터베이스가 아닌 애플리케이션 차원에서 제공한다.
엔티티 등록, 트랜잭션을 지원하는 쓰기 지연
옵션에 따라 설정할 수 있다.
만약 memberA와 memberB를 등록하면 일단 1차캐시에 저장해 놓고 SQL Insert문을 생성해 저장해놓는다.
어차피 조회는 1차캐시에서 찾아 반환할 수 있으므로 일단 DB까지 가지는 않는다.
이후 em.flush()를 수행하면 만들어두었던 insert문을 모두 DB에 보내게 된다.
영구히 저장하기 위해 commit이 필요하다.
엔티티 수정, 변경 감지
update를 수행하는 메서드를 따로 수행할 필요 없이 값을 바꾸면 알아서 감지해 update쿼리를 수행한다.
1차캐시는 각 entity의 스냅샷을 저장해둔다.
무언가 수정이 발생하면 스냅샷과 비교한다(Dirty Checking)
이후 commit 또는 flush를 수행하면 변경사항을 저장한다.
// 영속 엔티티 수정
memberA.setUsername("hi");
memberA.setAge(10);
// em.update(memberA) 같은 코드는 필요하지 않다.
transaction.commit();
엔티티 삭제
// 삭제 대상 엔티티 조회
Member memberA = em.find(Member.class, "memberA");
// 엔티티 삭제
em.remove(memberA);
플러시
- 영속성 컨텍스트를 비우지 않음
- 영속성 컨텍스트의 변경 내용을 데이터베이스에 동기화
- 트랜잭션이라는 작업 단위가 중요 -> 커밋 직전에만 동기화하면 된다.
영속성 컨텍스트를 플러시하는 방법
- 직접 호출 - em.flush()
- 자동 호출 - 트랜잭션 커밋
- 자동 호출 - JPQL 쿼리 실행
'Study > JPA' 카테고리의 다른 글
[JPA] Spring Data JPA와 QueryDSL 이해 (0) | 2022.01.13 |
---|---|
[JPA] 객체 지향 쿼리 (0) | 2022.01.13 |
[JPA] 양방향 매핑 (0) | 2022.01.12 |
[JPA] 연관관계 매핑 (0) | 2022.01.11 |
[JPA] JPA 필드와 컬럼 매핑 (0) | 2022.01.10 |