본문 바로가기
웹 개발/jpa

[jpa] 준영속이란? + 준영속 상태가 되는 법

by dani0312 2024. 1. 28.

본 글에 앞서 영속성 컨텍스트, 영속 상태에 대한 이해가 필요하다면 아래 글을 먼저 참조하는 것이 좋습니다.

2023.12.23 - [웹 개발/jpa] - [jpa] JPA 영속성 컨텍스트란? with EntityManager #1

2024.01.11 - [웹 개발/jpa] - [jpa] 영속성 컨텍스트란 with 1차 캐시 #2

 

 

 

본 글에서는 준영속 상태가 무엇인지, 그리고 준영속 상태로 만드는 방법 3가지에 대해 알아볼 것이다.

 

📌준영속 상태

◾ 준영속 상태란?

💧영속 -> 준영속

💧영속 상태의 엔티티가 영속성 컨텍스트에서 분리되는 것(detached)

💧영속성 컨텍스트가 제공하는 기능을 사용 못함

 

준영속 상태란 엔티티가 영속성 컨텍스트에서 분리되는 것이다. 쉽게 이야기하여, 빼버리는 것이다. 이렇게 되면 당연한 말일수 있지만 업데이트 할 때 기능이나 Dirty Checking이라던가 이런 기능들 자체를 사용하지 못하게 된다. 준영속 상태로 만드는 방법은 여러가지가 있다.

 

우선 준영속을 알아보기 전에 영속상태가 되는 것에 대해 다시 짚고 넘어가자.

 

 

 

◾영속상태가 되는 경우

영속 상태가 되는 주요한 2가지 경우이다.

1. `em.persist()`

2. `em.find()`

 

em.persist()의 경우 영속성 컨텍스트에 대해 학습할 때 알게 되었는데 em.find()의 경우 물음표를 가질 수 있다. 그런데 실제로 아래처럼 em.find()를 하여 객체를 찾아도 이것이 db에 영속상태로 되어있지 않으면 영속상태로 만든다. 

Member member = em.find(Member.class,150L);

 

이에 대한 설명은 아래를 참고하면 좋다.

2024.01.11 - [웹 개발/jpa] - [jpa] 영속성 컨텍스트란 with 1차 캐시 #2

 

[jpa] 영속성 컨텍스트란 with 1차 캐시 #2

본 글에 앞서 영속성 컨텍스트에 대해 잘 모른다면 아래 글을 먼저 참고하시는 것이 좋습니다. 2023.12.23 - [웹 개발/jpa] - [jpa] JPA 영속성 컨텍스트란? with EntityManager 이전 글에서는 영속성 컨텍스트

dani0312.tistory.com

 

준영속 상태는 영속성 상태에서 준영속 상태가 되는 것이므로 먼저 영속상태가 되는 방법에 대해 살펴보았다. 이제 준영속 상태가 되는 방법에 대해 알아보자.

 

 

 

◾준영속 상태로 만드는 방법

1. em.detach(entity) 특정 엔티티만 준영속 상태로 전환한다.

2. em.clear() : 영속성 컨텍스트를 완전히 초기화 한다.

3. em.close() : 영속성 컨텍스트를 종료한다.

 

 

1. em.detach(entity)

코드를 보며 준영속 상태로 만드는 detach() 메서드에 대해 이해해보자

try {
  Member member = em.find(Member.class,150L);//1번
  member.setName("AAAAA");//2번

  em.detach(member);//3번
  System.out.println("=======");
  tx.commit(); //4번

 

1번

150번 아이디의 객체를 찾아오려고 한다.

영속성 컨텍스트안에 1차캐시를 먼저 조회한다. → 1차캐시에 없어 db를조회한다  → 영속성 컨텍스트에도 올린다.

(db를 조회하는 것이므로 이 때 즉시 select쿼리가 생성된다. )

 

2번

setName()으로 객체를 변경하려하므로 update쿼리가 영속성 컨텍스트 안에 있는 쓰기지연SQL저장소에 쌓이게 된다.

→ 아직 트랜잭션이 커밋되기 전이므로 플러시가 일어나지 않는다. 즉 쿼리는 아직 저장소에 쌓여있고 db에 반영되지 않았다. 

 

3번

member객체를 detach()메서드를 이용해 준영속 상태로 만들었다. → member와 관련된 모든 것이 영속성 컨텍스트에서 빠지게 된다. 즉 member가 영속에서 준영속 상태가 된다. 

 

"======"

 

4번

트랜잭션 커밋이 일어난다. member가 준영속 상태에 있으므로 저장소에 쌓인 쿼리들이 날아가지 않는다. 애초에 영속성 컨텍스트에서 빠져나왔기 때문이다. 그러므로 “======” 이후에 업데이트 쿼리가 나가지 않는 것을 확인할 수 있다.

 

 

 

 

 

 

2. em.clear()

clear()메서드를 통해서도 준영속 상태로 만들 수 있다. 만일 이 메서드를 한다면 엔티티 매니저 안에 있는 영속성 컨텍스트를 통째로 다 지워버리는 것이다. 영속성 컨텍스트를 비워서(clear) 모든 영속성 컨텍스트에 존재하는 엔티티들을 분리한다. 

 

즉, 영속성 컨텍스트에서 관리 중인 모든 엔티티를 제거하고, 영속성 컨텍스트를 초기 상태로 되돌린다. (참고로 데이터베이스에 저장된 데이터는 영향을 받지 않는다.)

 

=> 한 마디로, 영속성 컨텍스를 전부 초기화한다! 

 

이 메서드로 코드를 통해 이해해보자

    Member member = em.find(Member.class,150L);//1번
    member.setName("AAAAA");//2번

    em.clear(); // 3번 영.컨 초기화
    Member member2 = em.find(Member.class,150L);//4번

    System.out.println("=======");
    tx.commit();

 

1번

영속성 컨텍스트의 1차캐시를 먼저 조회한다. → 1차 캐시에 없어 db를 조회한다.(select쿼리 생성) → 영속성 컨텍스트에 없으므로 올린다.

 

2번

update쿼리가 쓰기 지연 SQL저장소에 저장된다. 

 

3번

clear()메서드를 통해 영속성 컨텍스트를 초기화한다.

 

4번

3번에서 em.clear()로 초기화 하였으므로 영속성컨텍스트의 1차캐시를 조회하여도 존재하지 않는다. → db를 다시조회한다.(select쿼리 생성)  

 

"======"

 

아래 결과를 보면 select쿼리가 2번 나간 것을 확인할 수 있다.

 

1번에서 영속성 컨텍스트에 올려두었으므로 준영속 상태로 이변이 없다면 이를 조회해서 쓰면 되기 때문에 select쿼리를 생성할 필요가 없지만, 영속성 컨텍스트를 초기화 하였으므로 영속성 컨텍스트에 찾아가보아도 없는 것이다. 그러므로 db를 다시 조회하고, 다시 영속성 컨텍스트에 올린다. 

 

 

3. em.close() 

이 메서드는 아예 영속성 컨텍스트를 닫아버리는 것이다. 즉 이제 관리를 할 수 없고, 데이터를 변경하여도 변경이 되지 않는다.

 

 

 

 

쓰기 지연 저장소, 1차 캐시 등의 용어를 이해하기 어렵다면 글의 가장 첫번째에 달아둔 글 2개 링크를 먼저 참고하는 것이 좋다. 그곳에 자세히 서술하였으므로 이해하는데 도움이 될 것이다.

 


참고

자바 ORM 표준 JPA 프로그래밍 - 기본편 / 김영한 / 인프런 강의

 

 


/* 내가 추가한 코드 */ /* 내가 추가한 코드 끝끝 */