영속성 컨텍스트 2

엔티티 조회, 1차캐시

  • JPA에서 1차 캐시는 엔티티를 영속성 컨텍스트에서 관리하는 캐시를 의미한다.
  • find()나 getReference() 메서드로 조회한 엔티티 객체는 1차 캐시에 저장된다.
  • 같은 엔티티를 다시 조회할 경우 1차 캐시에서 먼저 조회하게 되어 DB에서 조회하지 않고 캐시된 엔티티를 반환한다.
  • 1차 캐시는 엔티티 매니저의 생명주기와 같이 유지된다.
  • 1차 캐시에 저장된 엔티티의 상태가 변경되면 엔티티 매니저는 변경 내용을 즉시 DB에 반영하지 않아도 된다.

 

엔티티 저장

  • 엔티티를 생성한 후 persist 메서드를 이용해 영속 상태로 만든다.
  • DB PK로 지정한 값을 키로, 엔티티 자체를 값으로 1차 캐시에 저장한다.

 

엔티티 조회 - 1차 캐시에서 조회

  • find 메서드를 사용하면 우선 DB가 아니라 1차 캐시를 조회한다.

 

엔티티 조회 - DB에서 조회

  • 찾고자 하는 값이 1차캐시에 없으면 DB를 조회한다.
  • 찾고자 하는 값이 DB에 있으면 이를 1차캐시에 저장하고 반환한다.
  • 엔티티 매니저는 DB 트랜잭션 단위로 만들고, 트랜잭션 종료 시 같이 삭제된다.
  • 즉, 영속성 컨텍스트와 1차캐시 역시 함께 삭제한다.
  • 즉, 굉장히 짧은 시간동안(하나의 트랜잭션 안)만 영향을 끼치기 때문에 큰 이득을 가져다주진 않는다. 여러 사용자들을 위한 캐시는 아니다. (앱 전체에 공유되는 캐시는 나중에 배울 2차캐시)

 

1차캐시 조회 예시

  • 조회를 했는데 SELECT 쿼리가 주어지지 않는다.
  • 1차캐시에 저장되어있기 때문에 DB에서 가져올 필요가 없기 때문이다.

 

  • (id = 1L인 Member 객체 저장되어있는 상태)

 

  • 위와같은 코드를 새로 실행을 하니 조회를 하면 이번에는 SELECT 쿼리가 실행된다.
  • 새로운 엔티티 매니저가 생성되어 먼저 DB에서 값을 찾아오고 1차 캐시에 저장한다. SELECT 쿼리를 실행된다.
  • 두 번째 조회 시, 영속성 컨텍스트에 있는 값을 조회하기 때문에 SELECT 쿼리를 실행하지 않는다.

 

 

영속 엔티티의 동일성 보장

  • 위에서 entityManager.find( … ) 는 DB에서 식별자 값이 1인 Member 엔티티를 조회하여 반환한다.
  • 그리고 이를 영속성 컨텍스트에 보관한다.
  • 이후 같은 식별자로 조회하면 이미 영속성 컨텍스트에 저장된 Member 엔티티를 반환하므로 세로운 쿼리를 실행하지 않는다.
  • 이렇게 같은 식별자 값을 같는 엔티티는 동일한 엔티티로 인식되고, 이름 영속 엔티티의 동일성 보장이라고 한다.
  • 즉, 영속 엔티티의 동일성 보장은 동일성이 아니라 식별자 값을 기준으로 한다.
  • 1차 캐시로 REPEATABLE READ 등급의 트랜잭션 격리 수준을 DB가 아닌 매플리케이션 차원에서 제공한다.
  • 이는 중복조회를 줄여주어 성능을 향상시키는데 도움이 된다.

 

 

트랜잭션을 지원하는 쓰기 지연

  • commit을 실행할 때 쿼리가 실행됨을 알 수 있다.
  • commit 하는 과정에서 INSERT SQL을 보낸다.
  • 하이버네이트 옵션 중 batch_size 를 사용해 사이즈만큼 모아서 한 번에 DB에 커밋할 수 있다. (버퍼링)

 

  • 영속성 컨텍스트 안에는 1차캐시 말고도 쓰기지연 SQL 저장소가있다.
  • 1차캐시 저장과 동시에 INSERT 쿼리도 생성되어 SQL 저장소에 저장된다.

 

  • 트랜잭션을 commit하는 순간에 쓰기지연 저장소에 있던 SQL들이 flush되어 DB에서 실행된다.

 

 

엔티티 수정 - 변경 감지

영속 엔티티를 조회해서 수정했다.

이후JPA에게 업데이트나 저장 등을 명령해야할 것 같지만,

그렇게 하지 않아도 Java Collection 처럼 처리해도 값이 적용되어있다.

  • 스냅샷이란 값을 읽어온 최초 시점의 상태를 갖고있는 것을 의미한다.
  • commit이 일어나면, 1차캐시의 엔티티와 스냅샷의 비교가 일어난다.
  1. commit을 명령하면 내부 flush()가 일어난다.
  2. JPA가 엔티티와 스냅샷을 전부 비교한다.
  3. 변경된 사항이 있을 경우 UPDATE 쿼리를 쓰기지연 SQL 저장소에 저장한다.
  4. DB에 반영하고 commit한다.

 

엔티티 삭제

'Spring > JPA 프로그래밍 - 기본편' 카테고리의 다른 글

준영속 상태  (0) 2023.04.10
플러시  (0) 2023.04.09
Hello JPA - 애플리케이션 개발  (0) 2023.03.28
Hello JPA - 프로젝트 생성  (0) 2023.03.27
JPA 소개  (0) 2023.03.27