JPA_영속성 컨텍스트란?

woonie·2022년 7월 5일
0

스프링으로 프로젝트를 진행하면서 JPA의 영속성 컨텍스트를 개념만 알고 별도로 정리하지 않고 넘어갔다.
지금 이렇게 하나하나 개념을 정리하고 있으니 JPA 영속성 컨텍스트도 다시 한번 익히고 정리해보려고 한다.

JPA를 공부하며 가장 중요하다고 생각하는 부분은 설계와 관련된 객체와 관계형 데이터베이스를 매핑하는 것(Object Relational Mapping)과 지금 정리해보려고 하는 JPA 내부 동작인 영속성 컨텍스트 이다.

1. 영속성 컨텍스트(Persistence Context)란?

  • 엔티티를 영구 저장하는 환경 이라는 의미
  • EntityManager.persist(entity); 동작
    • 실제 DB에 저장하는 것이 아니라 영속성 컨텍스트를 통해 Entity를 영속화 한다는 의미다.
    • 조금 더 구체적으로 표현하자면 persist() 시점에는 Entity를 영속성 컨텍스트에 저장한다는 것이다.
  • EntityManager를 통해 영속성 컨텍스트에 접근한다.
    • EntityManager가 생성되면 1:1로 영속성 컨텍스트가 생성된다.

2. 엔티티의 생명주기(Entity LifeCycle)

2-1. 비영속(new/transient)

  • 영속성 컨텍스트와 전혀 관계가 없는 상태
  • 객체를 생성만 한 상태(영속성 컨텍스트에 저장X)
    // 객체를 생성한 상태(비영속)
    Member member = new Member();
    member.setId("member1");
    member.setUserName("회원1");

2-2. 영속(managed)

  • 영속성 컨텍스트에 저장된 상태
  • Entity가 영속성 컨텍스트에 의해 관리되는 상태
       // 객체를 생성한 상태(비영속)
    Member member = new Member();
    member.setId("member1");
    member.setUserName("회원1");
    EntityManager entityManager = entityManagerFactory.createEntityManager();
    entityManager.getTransaction().begin();
    // 객체를 저장한 상태 (영속)
    entityManager.persist(member);

    EntityManager.persist(entity);
    => 영속 상태가 된다고 바로 DB에 쿼리가 날아가지 않는다.(DB저장 X)

2-3. 준영속(detached)

  • 영속성 컨텍스트가 관리하던 영속 상태의 Entity를 더 이상 관리하지 않는 상태
  • 영속성 컨텍스트에서 지운 상태
    // 회원 엔티티를 영속성 컨텍스트에서 분리, 준영속 상태
    entityManager.detach(member);
    // 영속성 콘텍스트를 비워도 관리되던 엔티티는 준영속 상태가 된다.
    entityManager.claer();
    // 영속성 콘텍스트를 종료해도 관리되던 엔티티는 준영속 상태가 된다.
    entityManager.close();

    준영속 상태의 특징
    1. 1차캐시, 쓰기 지연, 변경 감지, 지연 로딩을 포함한 영속성 컨텍스트가 제공하는 어떠한 기능도 동작하지 않는다.
    2. 식별자 값을 갖고 있다.

2-4. 삭제(removed)

  • Entity를 영속성 컨텍스트와 실제 DB에서 삭제
    // 객체를 삭제한 상태
    entityManager.remove(member);

3. 영속성 컨텍스트(Persistence Context)의 특징

3-1. 영속성 컨텍스트의 식별자 값

  • 영속성 컨텍스트는 Entity를 식별자 값으로 구분한다. 따라서 영속 상태는 식별자 값이 반드시 있어야 한다.

3-2. 영속성 컨텍스트와 데이터베이스 저장

  • JPA는 보통 트랜잭션을 커밋하는 순간 영속성 컨텍스트에 새로 저장된 Entity를 DB에 반영하는데 이를 flush 라고 한다.

4. 영속성 컨텍스트(Persistence Context)의 이점

4-1. 1차 캐시

  • 영속성 컨텍스트 내부에는 1차 캐시가 존재한다.
  • Map<key, Value> 로 1차 캐시에 저장된다.
    • Key : @Id로 선언한 필드 값(DB pk)
    • Value : 해당 Entity 자체
Member member = new Member();
member.setId("member1");
member.setUsername("회원1");
/* 영속 상태 (Persistence Context 에 의해 Entity 가 관리되는 상태) */
// DB 저장 X, 1차 캐시에 저장됨
entityManager.persist(member); 
// 1차 캐시에서 조회
Member findMember = entityManager.find(Member.class, "Member1");
  • 1차 캐시에 Entity가 있는 경우 이점
    • 조회할 때 이점이 생긴다.
    • entityManager.find() 를 하면 DB보다 먼저, 1차 캐시를 조회한다.
    • 1차 캐시에 해당 Entity가 존재하면 바로 반환한다.
  • 1차 캐시에 Entity가 없다면?
      1. DB에서 조회
      1. 해당 Entity를 DB에서 가져와서 1차 캐시에 저장한다.
      1. Entity를 반환

4-2. 동일성(identity) 보장

Member a = em.find(Member.class, "Member1");
Member b = em.find(Member.class, "Member2");
Systen.out.println(a == b); // 동일성 비교 true
  • 영속 Entity의 동일성(==비교)을 보장한다.(==비교를 하였을때 true임을 보장)
  • member1에 해당하는 Entity를 2번 조회하면 1차 캐시에 의해 같은 Reference로 인식
  • 하나의 Transaction안에서 같은 Entity 비교 시 true

4-3. Entity “등록” 시 트랜잭션을 지원하는 쓰기 지연 (Transactional Write-Behind)

  • entityManager.persist()
    • JPA가 insert SQL을 계속 쌓고 있는 상태
  • transaction.commit()
    • 커밋하는 시점에 insert SQL을 동시에 DB에 보낸다.
      동시에 쿼리들을 쫙 보낸다.(쿼리를 보내는 방식은 동시 or 하나씩 옵션에 따라)

4-4. 엔티티 “수정” 시 변경 감지 (Dirty Checking)

  • Entity를 수정할 때 단순히 Entity를 조회해서 데이터를 수정하고 commit하면 DB에 반영된다.

  • 즉, 데이터를 set하면 해당 데이터의 변경을 감지하여 자동으로 UPDATE Query가 나가는 것이다.

  • 변경 감지 매커니즘
    transaction.commit() 을 하면

    1. flush()가 일어날 때 엔티티와 스냅샷을 일일이 비교한다.
    2. 변경사항이 있으면 UPDATE Query를 만든다.
    3. 해당 UPDATE Query를 쓰기 지연 SQL 저장소에 넣는다.
    4. UPDATE Query를 DB에 반영한 후 commit()한다.



참고

https://www.inflearn.com/course/ORM-JPA-Basic

https://velog.io/@neptunes032/JPA-%EC%98%81%EC%86%8D%EC%84%B1-%EC%BB%A8%ED%85%8D%EC%8A%A4%ED%8A%B8%EB%9E%80

https://hckcksrl.medium.com/%EC%98%81%EC%86%8D%EC%84%B1-%EC%BB%A8%ED%85%8D%EC%8A%A4%ED%8A%B8-986464f8b1e8

https://willseungh0.tistory.com/65

https://sjh836.tistory.com/189

https://hibernate.org/orm/documentation/5.4/

https://www.slideshare.net/NHNFORWARD/2018-mybatis-jpa

profile
동료들과 함께하는 개발의 중요성에 관심이 많습니다. 언제나 호기심을 갖고 꾸준히 노력하는 개발자로서 성장하고 있습니다.

0개의 댓글