[정리] 영속성 컨텍스트 및 엔티티

📝 엔티티 매니저 팩토리와 엔티티 매니저

  • JPA가 제공하는 기능은 엔티티와 테이블을 매핑하는 설계부분과 매핑한 엔티티를 실제 사용하는 부분으로 나눌 수 있다.
  • 엔티티 매니저는 엔티티를 저장하고 수정하고 삭제하고 조회하는 등 엔티티와 관련된 모든 일을 처리한다. 즉, 엔티티를 관리하는 관리자다.
  • 엔티티 매니저 팩토리는 한개 만 만들어서 애플리케이션 전체에서 공유하도록 설계되어 있다.
  • 엔티티 매니저 팩토리는 여러 스레드가 동시에 접근해도 안전하지만, 엔티티 매니저는 여러 스레드가 동시에 접근하면 동시성 문제가 발생하므로 스레드 간에 절대 공유하면 안된다.
  • 엔티티 매니저 트랜잭션을 시작할 때 커넥션을 획득한다.

📝 영속성 컨텍스트란?

  • 영속성 컨텍스트(Persistence context)는 엔티티를 영구 저장하는 환경이다.
  • 엔티티 매니저로 엔티티를 저장하거나 조회화면 엔티티 매니저는 영속성 컨텍스트에 엔티티를 보관하고 관리한다.

1. 엔티티 생명주기

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

2. 영속성 컨텍스트 특징

  • 영속성 컨텍스트는 엔티티를 식별자 값으로 구분한다
  • JPA는 보통 트랜잭션 커밋하는 순간 영속성 컨텍스트에 새로 저장된 엔티티를 데이터베이스에
    반영하는데 이를 플러시(flush)라 한다.
  • 영속성 컨텍스트가 엔티티 관리할 경우의 장점
    • 1차 캐시
    • 동일성 보장
    • 트랜잭션을 지원하는 쓰기 지연
    • 변경 감지
    • 지연 로딩

3. 엔티티 조회

  • 영속성 컨텍스트는 내부에 캐시를 가지고 있는데 이것을 1차 캐시라 한다.
  • 영속상태의 엔티티는 모두 이곳에 저장된다. 즉, 영속성 컨텍스트 내부에 Map이 하나 있는데
    키는 @Id로 매핑한 식별자고 값은 엔티티 인스턴스이다.
  • em.find() 호출하면 먼저 1차 캐시에서 엔티티를 찾고 만약 1차 캐시에 없으면 데이터베이스에서 조회한다

4. 엔티티 등록

  • 엔티티 매니저는 트랜잭션을 커밋하기 직전까지 데이터베이스에 엔티티를 저장하지 않고 내부 쿼리 저장소에 insert sql을 차곡 모아둔다. 그리고 트랜잭션을 커밋할 때 모아둔 쿼리를 데이터베이스에 보내는데 이것을 트랜잭션을 지원하는 쓰기 지연(transactional write-behind)이라 한다
  • 트랜잭션을 커밋하면 엔티티 매니저는 우선 영속성 컨텍스트를 플러시한다.
  • 플러시는 영속성 컨텍스트의 변경 내용을 데이터베이스에 동기화하는 작업인데 이때, 등록, 수정, 삭제한 엔티티를 데이터베이스에 반영한다.
  • 이렇게 변경 내용을 데이터베이스에 동기화 한 후에 실제 데이터베이스 트랜잭션을 커밋한다.

5. 엔티티 수정

  • SQL을 사용하면 데이터를 수정할 때마다 쿼리가 생성이 된다. 이런 방식의 문제는 수정 쿼리가 많아지고 비즈니스 로직을 분석하기 위해 SQL을 계속 확인해야 된다. 즉, SQL에 의존적이게 된다.
  • JPA로 엔티티를 수정할 때는 단순희 엔티티를 조회해서 데이터만 변경하면 된다.
    엔티티의 데이터만 변경했는데도 데이터베이스에 반영되는 이유는 엔티티의 변경사항을 데이터베이스에 자동으로 반영하는 변경감지(dirty checking) 기능 때문이다.
  • JPA는 엔티티를 영속성 컨텍스트에 보관할 때, 최초 상태를 복사해서 저장해두는데 이것을 스냅샷이라 한다. 그리고 플러시 시점에 스냅샷과 엔티티를 비교해서 변경된 엔티티를 찾는다
  • JPA의 기본전략은 엔티티의 모든 필드를 업데이트 한다.
  • 수정 시 모든 필드를 사용하면 수정쿼리가 항상 같다. 따라서 애플리케이션 로딩 시점에 수정 쿼리를 미리 생성해두고 재사용할 수 있다.
  • 데이터베이스에 동일한 쿼리를 보내면 데이터베이 스는 이전에 한 번 파싱된 쿼리를 재사용할 수 있다.

6. 엔티티 삭제

  • em.remove()에 삭제 대상 엔티티를 넘겨주면 엔티티를 삭제한다.
  • 엔티티를 즉시 삭제하는 것이 아니라 엔티티 등록과 비슷하게 삭제 쿼리를 쓰기 지연 SQL 저장소에 등록한다.
  • 이후, 트랜잭션을 커밋해서 플러시를 호출하면 실제 데이터베이스에 삭제 쿼리를 전달한다.

'📚 Spring > Spring JPA' 카테고리의 다른 글

[정리] 준영속  (0) 2022.03.17
[정리] 플러시 (flush())  (0) 2022.03.16
@JsonIgnore  (0) 2020.09.04
[Spring JPA #12] 커스텀 리포지토리  (0) 2020.07.22
[Spring JPA #11] 쿼리 실습  (0) 2020.07.19

댓글

Designed by JB FACTORY