JAVA/JPA

[JPA] 영속성 컨텍스트 (Persistence Context) - (2)

4Legs 2021. 3. 30. 22:22

1차 캐시 (First Level Cache)

1차 캐시는 영속성 컨텍스트 내에 존재하는 캐시이다.

1차 캐시

영속성 컨텍스트에 엔티티가 저장되는 순간, 1차 캐시에 다음과 같은 형태로 저장된다.

{ key : @Id로 선언한 필드 값, value : 해당 엔티티 }

find()가 호출되는 순간, EntityManager 내부의 이 1차 캐시를 먼저 탐색하게 된다. 이 때, 찾는 엔티티를 발견했다면 즉시 반환한다.

만약 1차 캐시에 해당 엔티티가 존재하지 않는다면, 데이터베이스에서 조회한다.

※ 1차 캐시는 Global하지 않다. 즉, 영속성 컨텍스트끼리 이 1차 캐시를 공유하지 않는다.

 

객체의 동일성 보장

영속성 컨텍스트는 영속 상태의 엔티티들에 대한 동일성(Identity)을 보장한다.

1차 캐시에 의해, member 객체 하나를 두 번 조회해도 이 둘은 같은 객체(레퍼런스)가 된다.

애플리케이션 차원에서 1차 캐시에게 REPEATABLE READ 인 트랜잭션 격리 수준을 제공한다.

Member a = em.find(Member.class, "Member1");
Member b = em.find(Member.class, "Member1");

System.out.println(a == b);  //true

 

엔티티 등록 : 트랜잭션 지원 쓰기 지연 (Transaction Write-Behind)

트랜잭션 내부에서 persist() 가 호출될 때, EntityManager는 해당 엔티티를 1차 캐시에 저장한 후 쓰기 지연 SQL 저장소에 INSERT 쿼리를 생성해 쌓아 놓는다.

member1 엔티티가 영속화
member2 엔티티가 영속화

EntityManager는 트랜잭션의 커밋 시점쓰기 지연 SQL 저장소에 쌓아 둔 쿼리들을 데이터베이스에 전송한다.

이렇게 쌓여 있는 쿼리들을 데이터베이스에 실제로 전송하는 메소드가 후술할 flush()이다.

실제로 쿼리를 보내고 난 뒤 트랜잭션을 커밋하게 된다.

 

엔티티 수정 : 변경 감지 (Dirty Checking)

변경 감지가 일어나는 과정

엔티티에 수정 사항이 발생해도, 이를 update() 또는 persist()를 사용해 따로 영속성 컨텍스트에 알려주지 않아도 된다.

바로 변경 감지(Dirty Checking)가 발생하기 때문인데, flush() 또는 commit()이 발생할 경우 1차 캐시에 들어 있는 엔티티의 스냅샷과 엔티티를 비교변경 사항에 대해 자동으로 UPDATE SQL을 만들어 DB에 전송한다.

 

Reference

자바 ORM 표준 JPA 프로그래밍