본문 바로가기
Spring

[JPA]영속성 컨텍스트

by runlearn 2023. 9. 24.

영속성 컨텍스트

영속성 컨텍스트란 무엇인가?

  • 엔티티를 영구 저장하는 환경이라는 뜻을 가진다. 코드로 보면EntityManager.persist(entity); 에 해당한다.
  • 영속성 컨텍스트는 논리적인 개념으로 엔티티 매니저를 통해서 접근한다.
  • 서비스 별로 하나의 EntityManagerFactory가 존재하고 DB에 접근하는 트랜잭션이 발생하는 경우 스레드 별로 EntityManager를 생헝하여 영속성 컨텍스트에 접근한다.
    • 사용자로 부터 요청이 들어옴 -> EntityManagerFactory에서 요청당 1개의 EntityManager를 생성 -> EntityManager로 DB에 접근
  • EntityManager 에서 엔티티를 저장하거나 조회하는 경우 영속성 컨텍스트에서 엔티티를 보관하고 관리하게 된다.

EntityManager

  • EntityManager은 영속성 컨텍스트 내부의 엔티티를 관리한다.
  • JPA에서 제공하는 인터페이스로 Spring bean으로 등록되어 있어 @Autowired 를 이용하여 사용할 수 있다.
  • Query 메서드, SimpleJPARepository는 EntityManager를 쉽게 이용하기 위해 한번 더 추상화 한 것이다.

영속성 컨텍스트 특징

  • 1차 캐시
    • 영속 상태의 엔티티를 저장하는 곳으로 Map 형태이다. Key로는 @Id값, Value는 entity를 저장한다.
    • 만약 Id값으로 엔티티를 조회하는 경우, 먼저 1차 캐시에서 조회한다. 이 때 1차캐시에 해당 엔티티가 존재하면 DB를 조회하지 않는다. 1차 캐시에 엔티티가 없을 때 DB에서 쿼리를 날려 조회한다.
    • delete나 update를 하는 경우에도 내부적으로 Id로 조회를 한다.
    • 트랜잭션의 범위 안에서만 사용되는 범위가 짧은 캐시다.
  • 동일성(Identity) 보장
    • 영속성 컨텍스트에서 꺼낸 엔티티의 객체 주소는 동일하다.
    • 1차캐시로 REPEATABLE READ 트랜잭션 격리 수준을 DB가 아닌 애플리케이션 차원에서 제공한다.
    • 즉, 엔티티의 @Id (식별자) 값이 동일하면 동일한 객체이다.
  • 쓰기지연
    • 엔티티 값을 변경시 바로 DB에 반영하지 않고, 영속성 컨텍스트의 쿼리 저장소에 쿼리문을 저장해 놓고 트랜잭션 커밋 시점에 반영한다. (플러시 되거나 트랜잭션 커밋되는 시점)
  • 변경 감지 (Dirty Checking)

플러시

  • 영속성 컨텍스트의 데이터를 DB에 반영하는 역할을 한다. (영속성 컨텍스트를 비우는 것이 아님)
    • 영속성 컨텍스트 내 쿼리 저장소에 있는 SQL들이 DB에 실행된다.
    • 플러시 실행하면 더티체킹을 하여 스냅샷과 비교하여 수정된 내용을 반영한다.
  • 트랜잭션 커밋 시점에 영속성 컨텍스트의 내용을 DB에 반영한다.
  • 개발자가 직접 flush();를 호출하는 경우에도 DB에 영속성 컨텍스트의 내용이 반영된다.
  • JPQL 쿼리를 사용하는 경우 자동으로 flush();를 호출한다. (JPQL 호출할 때 영속성 컨텍스트의 데이터 들을 반영하지 못하면 오류가 발생할 수 있음)

Entity의 생명주기

비영속 상태

  • 영속성 컨텍스트와 전혀 관계가 없는 상태를 말한다. 즉, 엔티티를 생성했지만 영속성 컨텍스트에 저장하지 않은 상태다.

영속 상태

  • 영속성 컨텍스트에 저장된 상태, 영속성 컨텍스트의 관리를 받는다.
  • 트랜잭션 커밋 시점에 영속성 컨텍스트의 정보들로 DB에 쿼리를 날린다.
  • em.persist(entity);로 저장하거나 find() 로 엔티티를 찾는 경우 영속 상태가 된다.

준영속 상태

JPA가 관리하는 상태, 1차캐시에 존재하는 상태 => 영속 상태

그렇다면 준영속 상태란 무엇인가? 영속 상태의 엔티티가 영속성 컨텍스트에서 분리된 상태를 말한다. (detached) 그래서 영속성 컨텍스트가 제공하는 기능을 사용하지 못한다. (더티체킹 등..)

JPA가 관리하지 않기 때문에 트랜잭션 커밋 시점에 해당 엔티티에 대한 쿼리 등이 발생하지 않는다.

  • 준영속 상태 만드는 방법
    • em.detach(entity); 특정 엔티티만 준영속 상태로 전환
    • em.clear(); 영속성 컨텍스트 완전히 초기화
    • em.close(); 영속성 컨텍스트 종료

삭제 상태

  • 영속성 컨텍스트와 DB에서 해당 엔티티를 삭제한 경우

참고

  • 자바 ORM 표준 JPA 프로그래밍 - 기본편

'Spring' 카테고리의 다른 글

[JPA] 프록시  (1) 2023.10.09
[JPA] 더티체킹  (0) 2023.09.11
Spring boot에서 Redis 연동  (0) 2023.07.24
Spring profile  (0) 2023.07.09

댓글