영속성 컨텍스트

신경연·2023년 5월 10일
0

Spring

목록 보기
2/5

영속성 컨텍스트(Persistence Context)

  • 엔티티를 영구 저장하는 환경이라는 뜻이다.
  • 어플리케이션과 DB사이에서 객체를 보관하는 가상의 DB같은 역할을 한다.
  • 서비스별로 하나의 EntityManager Factory가 존재하며 Entity Manager Factory에서 DB에 접근하는 트랜잭션이 생길 때 마다 쓰레드 별로 Entity Manager를 생성하여 영속성 컨텍스트에 접근한다.

1. Entity의 생명주기


그림이 매우 직관적으로 그려져 있다.

비영속(new/transient)

엔티티 객체를 생성하였지만 아직 영속성 컨텍스트에 저장하지 않은 상태를 의미한다.

영속(managed)

영속성 컨텍스트에 저장된 상태.
바로 DB에 값이 저장되지 않고 트랜잭션의 커밋 시점에 DB에 쿼리로 날리게 된다.

준영속(detached)

영속성 컨텍스트에 저장되었다가 분리된 상태.

삭제(removed)

영속성 컨텍스트와 DB에서 해당 엔티티를 삭제하여 삭제된 상태.

2. 영속성 컨텍스트의 기능

1) 1차 Cache

  • 1차 캐시에는 영속 상태의 엔티티를 저장한다.
  • 1차 캐시는 key는 id값, value는 해당 entity값이 들어있는 Map의 형태로 만들어진다.
    • id가 아닌 다른 값을 이용하여 조회를 하면 1차 cache가 적용되지 않는다.
  • 하나의 Transactional에서 id값으로 조회하는 데이터들은 1차 cache에 저장을 하여 관리를 함으로써 JPA의 조회 성능이 올라간다.

1차 Cache 조회의 흐름
1. 1차 캐시에서 탐색한 ID값의 엔티티를 찾는다.
2. 탐색한 결과 해당 엔티티가 1차 캐시에 존재하면 값을 가져온다.
3. 탐색 결과가 1차 캐시에 존재하지 않다면 DB에서 값을 조회하고 조회한 데이터를 엔티티로 생성해 1차 캐시에 저장한다. (해당 엔티티를 영속 상태로 만든다.)
4. 조회한 엔티티를 반환한다.

2) 동일성(Identity) 보장

  • 영속성 콘텍스트는 영속 엔티티의 동일성을 보장한다.
    ※ 동일성은 값 뿐만 아니라 실제 인스턴스 자체가 같다는 뜻이다.

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

  • entity값을 변경하면 DB에 바로 업데이트 하지 않는다.
  • 트랜잭션 내부에서 영속 상태의 entity의 값을 변경하면 INSERT SQL Query들은 DB에 바로 보내지 않고 쿼리 저장소에 쿼리문들을 생성해서 쌓아둔다.
  • 쿼리 저장소에 쌓여있는 쿼리들은 entityManager의 flush()나 트랜잭션의 commit을 통해 보내지게 된다.

4) 변경 감지(Dirty Checking)

  • 엔티티의 수정이 일어나도 개발자는 영속성 컨텍스트에 따로 알려주지 않아도 영속성 컨텍스트가 알아서 변경 사항을 체크해준다. 이것을 Dirty checking이라고 한다.
  • 1차 캐시에 entity를 저장할때 스냅샷 필드도 따로 저장하여 commit이나 flush를 할 때 해당 entity와 스냅샷을 비교하여 변경사항이 있으면 알아서 UPDATE SQL을 만들어서 DB에 전송한다.

Dirty Checking의 흐름

  1. 트랙잭션을 커밋하면 entityManager의 내부에서 먼저 플러시가 호출된다.
  2. 엔티티와 스냅샷을 비교하여 변경된 엔티티를 찾는다.
  3. 변경된 엔티티가 있으면 수정 쿼리를 생성해서 쓰기 지연 SQL 저장소에 저장한다.
  4. 쓰기 지연 저장소의 SQL을 플러시한다.
  5. 데이터베이스 트랜잭션을 커밋한다.

5) 플러시 (flush)

  • 1차 캐시를 지우지 않고 쿼리를 DB에 날려서 DB와의 싱크를 맞추는 역할(동기화)을 한다.
    • 영속성 컨텍스트를 비우는 것이 아니다.
  • flush()를 하거나 트렌젝션의 commit을 하게 된다면 영속성 컨텍스트 내에 있는 쿼리저장소에 쌓여 있던 INSERT, UPDATE, DELETE SQL들이 데이터베이스에 날라간다.
  • flush를 실행하면 Dirty checking을 통해 스냅샷과 비교하여 수정된 entity를 찾고 UPDATE Query를 만들어 쿼리 저장소에 등록한 후 쿼리 저장소에 저장된 모든 쿼리를 DB에 보내어 동기화한다.
  • JPQL 쿼리문을 실행하기 전에 자동으로 flush()를 호출한다.
    • 사전에 영속성 콘텍스트에 추가한 데이터들이 flush() 되지 않아서 DB에 업데이트 되지 않았다면 JPQL쿼리문을 수행하는데 오류가 발생할 수 있기 때문이다.

내용이 직관적이라 이해가 어렵지 않았고,
여러 내용 중 가장 좋았던 블로그 링크를 두려고 한다.

https://velog.io/@seongwon97/Spring-Boot-%EC%98%81%EC%86%8D%EC%84%B1-%EC%BB%A8%ED%85%8D%EC%8A%A4%ED%8A%B8Persistence-Context

profile
반갑습니다

0개의 댓글