[TIL] 영속성 컨텍스트

김태하·2024년 2월 17일
0

Spring

목록 보기
7/7
post-thumbnail

📌 영속성 컨텍스트는 무엇일까?

JPA를 이해하는데 중요한 용어로써 쉽게 풀어서 “엔티티를 영구 저장하는 환경” 이라는 뜻이다.

EntityManager.persist(entity); 는 DB에 저장한다는게 아니라 영속성 컨텍스트를 통해서 이 엔티티라는 것을 영속화한다는 뜻이다. 즉, 엔티티를 영속성 컨텍스트라는 데 저장한다는 뜻이다.

그렇다면 언제 DB에 저장이 될까?

바로 Transaction을 commit하는 시점에 영속성 컨텍스트에 있는 애가 DB에 쿼리가 날라간다.


📌 엔티티의 생명주기

📍 비영속 (new/transient)

: 영속성 컨텍스트와 전혀 관계가 없는 새로운 상태.
Member member = new Member(); 와 같이 객체를 생성한 후 EntityManager에 아무것도 넣지 않아 JPA와 아무런 관계가 없는 상태이다.

📍 영속 (managed)

: 영속성 컨텍스트에 관리되는 상태.
객체를 생성한 후 EntityManager에 persist해서 객체를 넣으면 영속상태가 된다.

즉, EntityManager 안에 있는 영속성 컨텍스트라는 데를 통해서 이 객체가 관리된다는 뜻이다.

📍 준영속 (detached)

: 영속성 컨텍스트에 저장되었다가 분리된 상태.
EntityManager.detach(member); 엔티티를 영속성 컨텍스트에서 분리하는 작업이다.

📍 삭제 (removed)

: 삭제된 상태

em.remove(member); 실제 DB로 삭제 요청을 보낸다.


📌 영속성 컨텍스트의 이점

  • 1차 캐시
  • 동일성(identity) 이점
  • 트랜잭션을 지원하는 쓰기 지연 (transactional write-behind)
  • 변경 감지(Dirty Checking)
  • 지연 로딩(Lazy Loading)

📍 1차 캐시

보시다시피 영속성 컨텍스트에 존재하는 member1 이라는 객체를 조회할 때 1차 캐시에 이미 존재하기 때문에 DB에 접근할 필요가 없다.

1차 캐시는 데이터베이스의 한 트랜잭션 안에서만 효과가 있기 때문에 비즈니스 로직이 굉장히 복잡한 경우가 아니면 사실 큰 성능의 이점을 얻을 수는 없다.

📍 동일성 보장

마치 우리가 자바 컬렉션에서 꺼내서 똑같은 레퍼런스가 있는 객체를 꺼내면 == 비교를 했을 때 똑같은 것처럼 해준다.

📍 쓰기 지연

영속성 컨텍스트 내에 Insert문을 쌓고 있다가 트랜잭션을 commit 하는 순간에 지금까지의 쿼리문을 보내준다.

그렇다면 왜 commit하는 시점에 쿼리를 보낼까?

persist(member); 를 할때마다 쿼리를 날린다면 최적화 할 수 있는 여지 자체가 없어진다.

예를 들어 데이터베이스에 데이터를 아무리 집어넣어도 결국 commit을 하지 않으면 의미가 없어진다.

즉, commit하기 직전에 insert를 하고 한번에 commit을 하면 된다.

📍 변경 감지

데이터를 변경 후 이를 반영해줘야 하지 않을까?

JPA의 목적은 마치 Java 컬렉션을 다루듯이 객체를 다루는 것이다.

쉽게 생각하면 우리가 컬렉션에서 값을 꺼내서 변경하고 다시 집어 넣지 않는다.

즉, 데이터를 변경하면 이를 감지하여 자동으로 Update 쿼리를 날린다.

그렇다면 어떤 방식으로 이러한 과정이 이루어질까?

JPA는 Transaction의 commit 시점에 내부적으로 flush()라는게 호출이 된다.
호출이 된 후 엔티티랑 스냅샷을 비교하게 되는데 값이 변경된 것이 있다면 Update 쿼리를 쓰기 지연 SQL 저장소에 만들어둔다.

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

0개의 댓글