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

Harry park·2022년 6월 13일
1

JPA

목록 보기
1/8
post-thumbnail

📌JPA 영속성 컨텍스트

📍 Entity/EntityManager/EntityManager Factory

✍ EntityManager.persist(entity); 동작 관련 특징

  • 실제로 DB에 저장되는 것이 아니라, 영속성 컨텍스트에 보관/관리.
  • persist(entity)시점에는 entity영속성 컨텍스트에 저장된다는 의미

✍ Entity / EntityManager / EntityManagerFactory

📎 Entity

  • DB의 테이블과 매칭되는 개념

📎 EntityManager

  • Entity를 관리하는 역할을 수행하는 클래스
  • EntityManager내부에 영속성컨텍스트를 이용하여 관리한다.
  • Transaction 단위를 수행할 때마다 생성된다.
  • Thread간 공유되어서는 안된다.(사용 후 즉시 폐기)
  • 요청 시 생성되며 Transaction 후에는 close()되어야 한다.

📎 EntityManagerFactory

  • JPA는 EntityManagerFactory를 만들어야 한다.
  • Application이 loading 시점에 DB당 하나만 생성되어야 하며, WAS가 종료되는 시점에 EntityManagerFactory가 close()되어야 한다.

🎈 EntityManagerFactory는 thread-safe하지만, EntityManager는 thread-safe하지 않아 thread간 공유하면 안된다.

📍 JPA에서 가장 중요한 2가지 요소

✍ 객체와 관련된 DB 매핑(Object Relational Mapping)
↳ 설계와 관련된 내용
↳ 정적인 내용(static contents)
영속성 컨텍스트
↳ JPA 내부 동작과 관련된 부분

📍 영속성 컨텍스트란?

📖 개념

영속성 컨텍스트엔티티를 영구적으로 저장하는 환경을 의미한다. 어플리케이션과 DB사이에서 객체(Object)를 보관하는 가상의 데이터 베이스 역할을 한다. 엔티티 매니저를 통해 엔티티영속성 컨텍스트에 보관/관리된다.

📖 플러시

📖 영속성 컨텍스트의 변경내용을 DB에 반영하는 것
(영속성 컨텍스트에 저장된 DB Query를 DB에 날려주는 것)

Flush 방법

  • flush() : 직접 호출
  • 트랜잭션 커밋 : 플러시 자동 호출
  • JPQL 쿼리 실행 : 플러시 자동 호출

📖 특징

✍ 용어상 특징

  • 논리적인 개념으로, 눈에 보이지 않는다.
  • "Entity를 영구히 저장하는 환경"을 뜻한다.

✍ 기능상 특징

👉 식별자 값
: 영속성 컨텍스트는 엔티티를 식별자 값으로 구분한다.(반드시 있어야 함)
👉 영속성 컨텍스트에서 DB로의 저장(flush)
: JPA는 commit하는 순간 영속성 컨텍스트에 저장된 엔티티를 DB에 반영한다.

📖 영속성 컨텍스트의 장점

1차 캐시

: 영속성 컨텍스트 내부에 존재하는 캐시를 "1차 캐시"라고 한다.
: 1차 캐시의 Key는 식별자 값이고 값은 Entity Instace이다.

Member member = em.find(Member.class, 1);

✍ 조회 흐름
Step1. 1차 캐시에서 Entity 조회
Step2. 1차 캐시에 있으면 메모리에 있는 Entity를 조회 없으면 DB에서 조회
Step3. 조회한 데이터로 Entity를 생성해 1차 캐시에 저장(영속화)
Step4 .Entity 반환

동일성 보장

: 영속성 컨텍스트는 엔티티의 동일성을 보장한다.

Member a = em.find(Member.class, "member1");
Member b = em.find(Member.class, "member1");
System.out.print(a==b)			 // true return

쓰기 지연(transactional write-behinde)

: persist()를 사용해 객체를 저장해도 바로 DDLDB에 실행되는 것이 아니다. commit을 하기 직전까지 내부 쿼리 저장소에 모아두며, 트랜잭션을 commit할 때 DB에서 실행이 되는데 이를 쓰기 지연이라 한다.

변경 감지

: Entity 데이터 수정 시 update()를 별도로 하지 않더라도, 영속성 컨텍스트는 데이터의 변경을 감지하여 자동으로 insert, update가 실행된다.
✍ 흐름
1차 캐시에 Id, Entity, Snapshot이 저장
Step1. commit()이 실행되어 flush()되는 순간 Entity - Snapshot을 비교한다.
Step2. 변경사항이 있으면 Update Query가 쓰기 지연 SQL저장소에 저장된다.
Step3. DB에 쿼리가 반영되고 commit된다.

지연 로딩(Lazy loading)

📍 엔티티의 생명주기(Entity LifeCycle)

비영속(new / transient)

  • 영속성 컨텍스트와 전혀 관계가 없는 상태
  • 인스턴스를 생성만한 상태
Member member = new Member();
member.setUserName("GreyTomato");

영속(managed)

  • 영속성 컨텍스트에 저장된 상태
  • Entity가 영속성 컨텍스트에 의해 관리되고 있는 상태
Member member = new Member();
member.setUserName("GreyTomato");

EntityManager entityManager = EntityManager.createEntityMnager(); 
entityManager.getTransaction().begin();

// 영속(DB에 저장된 상태 X, commit되어야 저장)
entityManager.persist(member);

준영속(detached)

  • 영속성 컨텍스트에서 저장되었다가 분리된 상태
  • 영속성 컨텍스트에서 제거된 상태
entityManager.detach(member);
// 영속성 컨텍스트를 비워도 준영속 상태가 된다.
entityManager.clear();
// 영속성 컨텍스트를 종료해도 준영속 상태가 된다.
entityManager.close();

📖 1차 캐시, 쓰기 지연, 변경 감지, 지연 로딩 등 영속성 컨텍스트가 제공하는 어떠한 기능도 동작하지 않게 된다.
📖 식별자 값을 가지고 있다.

삭제(removed)

  • 엔티티를 영속성 컨텍스트와 데이터베이스에서 삭제
entityManager.remove(member);

개인적으로 공부하며 기록한 내용으로, 틀린 내용이 있는 경우 덧글을 달아주시면 감사하겠습니다. 😍

profile
Jr. Backend Engineer

0개의 댓글