영속성 컨텍스트

스프링부트 프로젝트를 하다 영속성 개념이 매우 중요하다는 것을 들었다.
이 기회에 영속성에 대해서 알아볼까 한다.

영속성

JPA를 이해하는데 가장 중요한 개념으로 엔티티를 영구 저장하는 환경
어플리케이션과 DB사이에서 객체를 보관하는 가상의 DB같은 역할을 함.

영속성 진행과정

서비스별로 하나의 EntityManager Factory가 존재하며 Entity Manager Factory에서
디비에 접근하는 트랜잭션이 생길 때 마다 쓰레드 별로 Entity Manager를 생성하여 영속성 컨텍스트에 접근한다.
EntityManager에 엔티티를 저장하거나 조회하면 EntityManager는 영속성 컨텍스트에 엔티티를 보관하고 관리한다.
영속성 컨텍스트는 EntityManager를 생성할 때 만들어지며 EntityManager를 통해 영속성 컨텍스트에 접근하고 관리한다.
다음 코드로 Entity를 영속성 컨텍스트에 저장할 수 있다.

entityManager.persist(entity);

Spring에서는 EntityManager를 주입하여 사용하면 같은 트렌잭션의 범위에 있는 EntityManager는 같은 영속성 컨텍스트에 접근한다.
(J2EE와 같은 스프링 프레임워크 같은 컨테이너 환경은 Entity Manager와 영속성 컨텍스트의 관계가 N:1이 가능하다. 하지만 J2SE와 같은 환경은 1:1이다.)

EntityManager

EntityManager는 영속성 컨텍스트 내에서 Entity들을 관리하고 있다.
EntityManager는 JPA에서 제공하는 interface로 spring bean으로 등록되어 있어 Autowired로 사용할 수 있다.

@Autowired
private EntityManager entityManager;

Query Method, Simple JPA repository는 직접적으로 entityManager를 사용하지 않도록 한번 더 감싸준 것이다.
spring jpa에서 제공하지 않는 기능을 사용하거나 특별한 문제가 있어서 별도로 customizing을 해야한다면 entityManager를 직접 받아서 처리한다.

EntityManager는 Entity Cache를 갖고 있다.

Entity의 생명주기

비영속(new/transient)

  • 영속성 컨텍스트와 전혀 관계가 없는 상태
  • 엔티티 객체를 생성하였지만 아직 영속성 컨텍스트에 저장하지 않은 상태를 의미한다.
      //객체만 생성한 비영속상태 
      User user = new User();
    

    영속(managed)

  • 영속성 컨텍스트에 저장된 상태
  • 엔티티가 영속성 컨텍스트에 의해 관리된다.
  • 영속 상태가 되었다고 바로 DB에 값이 저장되지 않고 트렌젝션의 커밋 시점에 영속성 컨텍스트에 있는 정보들을 DB에 쿼리로 날리게 된다.
    @Autowired
    private EntityManager entityManager;
    // Class내에 Autowired로 EntityManager추가
    
      //객체만 생성한 비영속상태 
      User user = new User();
        
      // 객체를 저장한 영속상태
      entityManager.persist(user);
    

준영속(detached)

  • 영속성 컨텍스트에 저장되었다가 분리된 상태
  • 엔티티를 준영속 상태로 만드려면 entityManager.detach()를 호출한다.
      // 영속 -> 준영속
      // user엔티티를 영속성 컨텍스트에서 분리하면 준영속 상태가 된다.
      entityManager.detach(user);
      // 영속성 콘텍스트를 비우면 관리되고 있던 엔티티들은 준영속 상태가 된다. (대기 상태에 있는 변경 데이터들도 삭제)
      entityManager.clear();
      // 영속성 콘텍스트를 종료해도 관리되던 엔티티들은 준영속 상태가 된다.
     	entityManager.close();
        
      // 준영속 -> 영속 
      // detach를 하여 준영속상태에 빠진 entity를 merge를 하면 다시 영속 상태가 된다.
      entityManager.merge(user); 
    

    준영속 상태의 특징으로는 1차 캐시, 쓰기 지연, 변경 감지, 지연 로딩을 포함한 영속성 컨텍스트가 제공하는 어떠한 기능도 동작하지 않으며 식별자 값을 가지고 있다는 것이다.

삭제(removed)

  • 영속성 컨텍스트와 DB에서 해당 엔티티를 삭제하여 삭제된 상태이다.
      // user엔티티를 영속성 컨텍스트와 DB에서 삭제
      entityManager.remove(user);
    

Comments