개발자 취업준비/DataBase JPA

준영속 상태

naspeciallist 2025. 5. 5. 22:23

본 글은 https://www.inflearn.com/course/ORM-JPA-Basic/dashboard 강의를 바탕으로 작성한 글입니다.

 

1. 준영속 상태란


영속에서 준영속으로 가는 상태를 준영속 상태라고 합니다. 영속상태에서 엔티티가 영속성 컨텍스트에서 분리가 되는 상태입니다.

영속성 컨택스트가 제공하는 기능을 사용하지 못합니다.

영속상태란 1차캐시에 데이터베이스 값이 올라온 상태 즉 JPA에 의해 관리받고 있는 상태라 볼 수 있습니다.

준영속 상태란 이렇게 JPA에 관리받고 있는 상태에 엔티티를 관리되지 않은 상태로 빼버리는 것 입니다. 이렇게 되면 JPA가 제공하는 기능을 사용하지 못하게 됩니다.

 

준영속 상태로 만드는 방법은 다음과 같습니다.

  1. em.detach(entity): 특정 엔티티만 준영속 상태로 전환
  2. em.clear() : 영속성 컨텍스트를 완전히 초기화
  3. em.close() : 영속성 컨텍스트를 종료

 

예시를 들어보겠습니다.

try{
	Member member = em.find(Member.class, 150L);
	member.setName("?????")
	
	System.out.println("==========")
	tx.commit()
} catch (Exception e) {
	tx.rollback();

 

위 코드같은 경우에는 150번을 조회해서 이름을 ?????로 바꾸는 로직입니다.

 

이 로직에서 em.find로 값을 가져 올 때는 이 멤버엔티티는 영속상태가 됩니다. em.find를 통해 150번의 값을 가져올 때 영속성컨텍스트에 값이 없기 때문에 데이터베이스를 조회하여 150번의 값을 가져와 1차캐시에 올리게 됩니다. 이렇게 영속 상태로 엔티티를 변경하게 됩니다. 그리고 값을 변경하니까 이제 변경감지를 통해서 업데이트 쿼리를 실행하게 됩니다.

 

근데 만약에 더 이상 영속성 컨텍스트로 관리하기가 싫어진다면 어떻게 될까요? em.detach를 통해 영속성 컨택스트에서 분리를 할 수 있습니다. 영속성 컨택스트에서 이 멤버 엔티티를 분리하여 jpa에서 관리를 안하게 만들 수도 있습니다. 그러면 이제 트랜잭션을 커밋할 때 아무일도 일어나지 않게 됩니다.

 

코드를 다음과 같이 변경하겠습니다.

try{
	Member member = em.find(Member.class, 150L);
	member.setName("?????")
	
	em.detach(member);
	
	System.out.println("==========")
	tx.commit()
} catch (Exception e) {
	tx.rollback();

 

 

em.detach(member)을 통해 member엔티티를 영속성 컨텍스트에서 분리하겠습니다. 그리고 실행시키면 결과값이 다음과 같이 나오게 됩니다.

// em.detach(member) 적용 전
==========
select 쿼리실행
update 쿼리실행

// em.detach(member) 적용 후
select 쿼리실행
==========

 

em.detach(member)을 실행시키면 트랜잭션을 커밋할 때 아무일도 일어나지 않게 됩니다. 왜냐하면 JPA에서 이제 더 이상 관리를 안하니까 영속성 컨텍스트에서 엔티티가 제외가 되버리게 됩니다.

 

이렇게 영속 상태였다가 영속성 컨텍스트에서 빠지는 상태를 이제 준영속 상태라고 합니다.

 

em.detach(member)메소드를 em.clear()로 변경하여도 똑같은 결과값이 발생하게 됩니다.

 

영속 상태를 준영속 상태로 만들게 되면 다음과 같은 결과값을 발생시킬 수도 있습니다.

try{
	Member member = em.find(Member.class, 150L);
	member.setName("?????")
	
	em.clear();
	Member member = em.find(Member.class, 150L);
	
	System.out.println("==========")
	tx.commit()
} catch (Exception e) {
	tx.rollback();

 

m.clear()을 통해 준영속 상태를 만든 뒤 다시 조회 메서드를통해서 영속상태로 만들어 보겠습니다.

그럼 결과값이 다음과 같이 나오게 됩니다.

select쿼리 실행
select쿼리 실행
==========

 

원래 조회메서드를 2번 실행시키게 되면 1차캐시에 값이 저장되어 있기 때문에 select쿼리는 한번만 실행이 되게 됩니다. 하지만 em.clear()를 통해 영속성 컨텍스트에서 분리했으므로 1차캐시의 값이 없어지기 때문에 똑같은 조회메서드를 두번 사용을 해도 두번째 조회메서드에서는 JPA가 1차캐시에서 이전에 조회된 값을 찾을 수 없기 때문에 데이터베이스에서 다시 값을 조회하게 됩니다. 영속성 컨텍스트가 한번 초기화가 되면 select쿼리는 총 두번 실행되게 됩니다.

 

1차 캐시와 관계없이 테스트 케이스를 작성할 때 준영속 상태를 이용 할 수 있습니다.

'개발자 취업준비 > DataBase JPA' 카테고리의 다른 글

필드와 컬럼 매핑  (0) 2025.05.08
엔티티 매핑  (0) 2025.05.06
플러시  (0) 2025.05.04
영속성 컨텍스트  (0) 2025.05.01
JPA 이해하기  (0) 2025.05.01