본문 바로가기
BackEnd/JPA

[JPA] 스프링 데이터 JPA 이야기 번외편 - 영속성 컨텍스트

by 뽀뽀이v 2020. 10. 5.

이 글은 김영한 님의 자바 ORM 표준 JPA 프로그래밍 책을 읽고 복습 차원에서 적은 글입니다.

JPA 이야기 2부 다음으로 JPA의 영속성 컨텍스트의 개념에 대해서 알아보자!

영속성 컨텍스트란?

우리말로 번역하기는 어렵지만 해석하자면 '엔티티를 영구 저장하는 환경'이라는 뜻이다.

아래의 'entityManager.persist(member);'는 단순히 저장한다고 표현했지만 정확히 이야기하면 엔티티 매니저를 사용해서 회원 엔티티를 영속성 컨텍스트에 저장한다.

@Component
@Transactional
public class JpaRunner implements ApplicationRunner {

    @PersistenceContext
    EntityManager entityManager;

    @Override
    public void run(ApplicationArguments args) throws Exception {
        // 회원 엔티티
        Member member = new Member();
        member.setUsername("giuly");
        member.setPassword("1026");

        entityManager.persist(member);
}

엔티티의 생명주기

  • 비영속(new/transient) : 영속성 컨텍스트와 전혀 관계가 없는 상태
  • 영속(managed) : 영속성 컨텍스트에 저장된 상태
  • 준영속(detached) : 영속성 컨텍스트에 저장되었다가 분리된 상태
  • 삭제(removed) : 삭제된 상태

엔티티 생명주기

비영속

순수한 객체 상태이며 아직 저장하지 않았다. 영속성 컨텍스트와 데이터베이스와는 전혀 관련이 없다.이를 비영속 상태라고 한다.

Member member = new Member();
member.setUsername("giuly");
member.setPassword("1026");

 

 

비영속 상태

영속

영속성 컨텍스트가 관리하는 상태를 영속된 상태라고 한다. 즉 영속 상태라는 것은 영속성 컨텍스트에 의해 관리된다라는 뜻이다.

Member member = new Member();
member.setUsername("giuly");
member.setPassword("1026");

entityManager.persist(member);

영속 상태

준영속

영속성 컨텍스트에서 관리하던 엔티티를 관리하지 않으면 준영속 상태가 된다. 준영속 상태를 만들려면 다음을 호출하면 된다. 

Member member = new Member();
member.setUsername("giuly");
member.setPassword("1026");

entityManager.persist(member);

entityManager.detach(member);
// 초기화 해도 준영속 상태가 된다.
entityManager.close();
entityManager.clear();

삭제

엔티티를 영속성 컨텍스트와 데이터베이스에서 삭제한다.

entityManager.remove(member);

영속성 컨텍스트의 특징

영속성 컨텍스트와 식별자 값

영속 상태는 반드시 식별자 값이 있어야 한다. 식별자 값이 없으면 예외가 발생한다.

 

영속성 컨텍스트와 데이터베이스 저장

JPA는 보통 트랜잭션을 커밋하는 순간 영속성 컨텍스트에 새로 저장된 엔티티를 데이터베이스에 반영하는데 이것을 플러시라고 한다.

 

엔티티 관리의 장점

  • 1차 캐시
  • 동일성 보장
  • 트랜잭션을 지원하는 쓰기 지연
  • 변경 감지
  • 지연 로딩

JPA를 사용하면서 가장 특이 했던 변경감지에 대해서만 설명하도록 하겠다.

 

변경 감지(Dirty Checking)

// 엔티티 조회
Member memberA = entityManager.find(Member.class, "memberA");


memberA.setUsername("giuly");
memberA.setPassword("1026");

// entityManager.update(member); <== 이런 코드가 있어야 하지 않을까?

위의 엔티티의 데이터만 변경했는데 알아서 변경 감지 후 데이터베이스에 자동 반영한다.

조회를 하면 영속성 컨텍스트에 최초 상태를 복사해서 저장해두는데 이를 스냅샷이라고 한다. 스탭샷과 변경된 엔티티를 비교해서 다음과 같이 DB에 반영한다.

변경 감지

 

댓글