chae._.chae

Persistence Context란 ? 본문

스프링/스프링 공부

Persistence Context란 ?

walbe0528 2022. 2. 27. 10:16
728x90
반응형

🙋 EntityManagerFactory와 EntityManager란 ?

  • EntityManagerFactory

데이터베이스를 하나만 사용하는 애플리케이션들은 일반적으로 EntityManagerFactory를 하나만 생성한다. EntityManagerFactory는 여러 스레드가 동시에 접근해도 안전하므로, 서로 다른 스레드간에 공유가 가능하다. 

EntityManager를 생성한다. 

 

  • EntityManager

EntityManager는 Entity를 저장하는 메모리상의 데이터베이스이다.

Entity를 저장/조회/수정/삭제하는 등 Entity와 관련된 일을 수행한다. 

EntityManagerFactory와 달리 여러 스레드에서 동시에 접근할 수 없어 공유가 불가능하다.

EntityManager를 EntityManagerFactory를 통해 생성하지 않고,

일반적으로 스프링에서 관리하는 EntityManager를 아래와 같이 선언하여 사용한다. 

 

@PersistenceContext
private EntityManager em;  // 영속성 컨텍스트내에서 entity들을 관리하는 역할

 

🙋 Persistence Context란 ?

JPA에서 중요한 개념으로, 눈에 보이지 않는 논리적 개념이다. 

영속성 컨텍스트는 entity를 영구 저장하는 환경을 의미한다. 

EntityManager를 이용해 Entity를 저장/조회할 때, EntityManager는 영속성 컨텍스트에 Entity를 보관한다. 

 

@PersistenceContext
private EntityManager em;  // 영속성 컨텍스트내에서 entity들을 관리하는 역할

public Long save(Member member){
    em.persist(member);
    return member.getId();
}

위의 코드처럼 em이라는 em.persist(member);를 실행하면, 영속성 컨텍스트가 Entity를 관리해준다. 

실제로는 DB에 저장하는 것이 아니라, 영속성 컨텍스트를 통해서 Entity를 영속화한다는 뜻이다.

(persist( ) 시점에 Entity를 영속성 컨텍스트에 저장)

영속성 컨텍스트는 EntityManager를 하나 생성할 때 하나가 생성되며, EntityManager를 통해 접근할 수 있다. 

 

 

🙋 엔티티의 생명주기(Entity LifeCycle)란 ?

  • 비영속(new/transient)

영속성 컨텍스트와 전혀 관계가 없는 상태

객체를 생성'만' 한 상태

 

  • 영속(managed)

영속성 컨텍스트에 저장된 상태 (Entity가 영속성 컨텍스트에 의해 관리된다)

EntityManager.persist(Entity);

 

  • 준영속(detached)

영속성 컨텍스트에 저장되었다가 분리된 상태

영속성 컨텍스트가 영속 상태였던 Entity를 관리하지 않는다. 

EntityManager.detached(Entity);  -> 영속상태가 된다고 바로 DB에 쿼리가 날라가지 않는다. (즉, DB에 저장되지X)

transaction.commit( ); -> 트랜잭션의 commit시점에 영속성 컨텍스트에 있는 정보들이 DB에 쿼리로 날라간다. (flush)

 

  • 삭제(removed)

영속성 컨텍스트와 데이터베이스에서 Entity가 삭제된 상태

EntityManager.remove(Entity);

 

 

🙋 영속성 컨텍스트의 특징

 

영속성 컨텍스트는 Entity를 식별자 값으로 구분한다. 따라서, 영속상태는 반드시 식별자 값이 존재한다. 

트랜잭션의 commit시점에 영속성 컨텍스트에 새로 저장된 Entity가 DB에 저장되는데, 이를 flush라 한다.

 

동일성 보장

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

 

** 동일성 : 두 객체의 주소값이 동일하여, 두 벼누가 같은 객체를 가리킨다는 의미이다. == 를 사용해 비교한다.

** 동등성 : 두 객체가 같은 정보를 갖고 있는 경우이다. 변수가 참조하고 있는 객체의 주소가 다르더라도 내용만 같으면 동등하고 표현한다. equals 연산자를 통해 판별

 

@Test
@Transactional
@Rollback(false)
public void testMember() throws Exception {
    // given
    Member member = new Member();
    member.setUsername("memberA");

    // when
    Long saveId = memberRepository.save(member);
    Member findMember = memberRepository.find(saveId);

    // then
    Assertions.assertThat(findMember.getId()).isEqualTo(member.getId());
    Assertions.assertThat(findMember.getUsername()).isEqualTo(member.getUsername());
    Assertions.assertThat(findMember).isEqualTo(member);
    System.out.println(" findMember == member: " + (findMember == member));
}

같은 트랜잭션 안에서 저장하고 조회했으므로, 영속성 컨텍스트가 동일하기에 테스트시 True로 나온다. 

같은 영속성 컨텍스트 안에서는 Id값이 같으면 같은 entity로 인식한다. 

 

1차 캐시

영속성 컨텍스트 내부에 있는 캐시를 1차 캐시라 한다. 영속 상태의 엔티티를 이곳에 저장한다.  

Map<Key, Value>로 1차 캐시에 저장되며, 키는 식별자값이고(@Id 로 선언한 필드), 값은 Entity 자체이다. 

 

조회 흐름

  • 1차 캐시에서 해당 entity를 탐색한다. 
  • 1차 캐시에 없으면 DB에서 조회한다.
  • 가져온 데이터를 1차 캐시에 저장하고 반환한다. 

 

 

728x90