[JPA] EntityManager, 영속성 컨텍스트

2020. 2. 17. 00:17· Java/JPA
목차
  1. Entity Manager 생성
  2. 영속성 컨텍스트 (Persistence Context)
  3. 생명 주기
  4. 플러시 (flush)
  5. 종료
  6. 병합

김영한 님의 [자바 ORM 표준 JPA 프로그래밍]을 읽고 내용을 정리한 것입니다.

교보문고 링크

EntityManager와 영속성 컨텍스트

mybatis처럼 직접 SQL을 작성하거나 JPA를 활용한 개발을 할 때는 눈에 보이는 것 이상의 차이가 있다.

가장 사소한 예시를 들어보자면 CRUD로 불리는 가장 기본적인 4가지 동작 중 UPDATE는 JPA에 존재하지 않는다.

그럼에도 JPA는 업데이트 동작을 잘 수행한다.

영속성 컨텍스트가 데이터의 변경을 감지하여 자동으로 update 쿼리를 실행하기 때문이다.

JPA는 EntityManager와 영속성 컨텍스트를 통해 데이터의 상태 변화를 감지하고 필요한 쿼리를 자동으로 수행한다.

Spring boot + Spring Data를 사용하여 막 JPA를 배우는 상황이면 EntityManager를 한 번도 못 봤을 수 있는데,

Application이 시작될 때 EntityManager를 자동으로 bean에 등록하고 우리가 알지 못하는 사이에 가져다 사용하고 있다.

Entity Manager 생성

// name에 persistance unit name을 등록할 수 있다.
EntityManagerFactory emf = Persistance.createEntityManagerFactory("name");
EntityManager em = emf.createEntityManager();

EntityManager를 생성할 땐 가급적 팩토리를 활용한다.

EntityManagerFactory는 Thread safe한 처리가 되어 있으나, EntityManager는 그렇지 않기 때문에 스레드 간 공유에 주의해야 한다.

영속성 컨텍스트 (Persistence Context)

엔티티를 영구 저장하는 환경이다.

Java 영역에서 데이터를 관리하여 DB 접근을 최적화하는 역할을 담당한다.

생명 주기

엔티티는 4가지 상태가 존재한다.

  1. 비영속

    • 영속성 컨텍스트와 연관이 없는 상태
  2. 영속

    • 영속성 컨텍스트에서 관리 중인 상태
  3. 준영속

    • 영속성 컨텍스트에 저장되어 있었으나 분리된 상태
  4. 삭제

    • 영속성 컨텍스트에서 완전히 삭제된 상태

비영속

@Entity 어노테이션을 갖는 엔티티 인스턴스를 막 생성했을 때는 영속성 컨텍스트에서 관리하지 않는다.

EntityManager의 persist 메소드를 사용하여 영속 상태로 변경할 수 있다.

em.persist(someEntity);

영속

EntityManager를 통해 데이터를 영속성 컨텍스트에 저장했다.

JPA는 일반적으로 id 필드가 존재하지 않으면 예외를 뱉어내는데, 영속 상태의 엔티티를 관리하기 위해서다.

id로 데이터를 관리하기 때문에 꼭 필요한 것이다.

이 상태가 되면 몇 가지의 장점을 갖게 된다.

  1. 1차 캐시

    • em.find(key)를 호출하면 영속성 컨텍스트에 캐시된 데이터를 먼저 찾는다.
    • 캐시된 데이터가 없다면 DB에 접근하여 데이터를 로드하고 1차 캐시 데이터에 저장한다.
    • 1차 캐시의 존재로 Java 영역에서 REPEATABLE READ 등급의 트랜잭션 격리 수준을 활용한다.
  2. 동일성 보장

    • JPA를 통해 불러온 데이터는 모두 캐시 데이터에 저장되기 때문에 같은 id를 가진 데이터는 같은 데이터이다.

      • 일반적으로 Java에서 '같다'라는 기준은 Identity(hashcode) / Equality(equals)이다.
      SomeEntity a = em.find(SomeEntity.class, "1");
      SomeEntity b = em.find(SomeEntity.class, "1");
      // a == b : true (Identity)
      // a.equals(b) : true (Equality)
  3. 트랜잭션 지원하는 쓰기 지연

    • Transaction이 시작된 이후 JPA가 생성한 쿼리는 모두 쓰기 지연 저장소에 저장된다.
    • commit이 수행되면 저장된 모든 쿼리를 실행한다.
  4. 변경 감지

    • SQL을 직접 활용하여 개발하면 update문을 수행할 때 매우 귀찮은 점이 있다.
    • 컬럼 1개, 2개, 3개, ... N개를 수정해야 할 때를 모두 쿼리로 작성해야 하는 것이다.
    • 이렇게 되면 비즈니스 로직은 SQL에 의존할 수밖에 없다.
    • JPA는 데이터를 저장하기 전 영속성 컨텍스트에 저장된 데이터가 있는지 확인한다.
    • 동일 데이터가 존재하면 update, 없으면 insert를 수행한다(upsert).
    • JPA가 실제로 수행하는 쿼리는 모든 컬럼을 변경한다.
      • 컬럼이 굉장히 많은(30개 이상) 테이블이 아니면 성능에 크게 영향을 미치지 않는다.
      • 엔티티 클래스에 @DynamicUpdate를 붙여주면 SET절에 변경된 데이터만 삽입된다.
  5. 지연 로딩

준영속

원래 영속 상태였으나 영속성 컨텍스트에서 분리되어 더 이상 관리하지 않는 데이터가 된 상태이다.

영속 상태의 엔티티를 detach 시키거나 영속성 컨텍스트 자체가 초기화 / 종료되면 컨텍스트 내부의 모든 데이터는 준영속 상태가 된다.

관리되지는 않는 상태이지만 JPA의 지원을 받지 못할 뿐, 정상적인 데이터를 갖는 인스턴스이다.

// 1.
em.detach(someEntity);
// 2.
em.close();
// 3.
em.clear();

삭제

엔티티를 영속성 컨텍스트와 DB 양쪽에서 모두 삭제한다.

em.remove(someEntity);

플러시 (flush)

영속성 컨텍스트의 변경 내용을 DB에 반영하는 절차이다.

플러시를 수행하면 아래 순서대로 동작한다.

  1. 데이터의 변경을 감지한다.
  2. 생성된 쿼리를 쓰기 지연 저장소에 등록한다.
  3. commit되면 저장되어 있던 쿼리를 모두 수행한다.

em.flush()를 활용하면 직접 플러시할 수 있다.

플러시 모드

  1. @FlushModeType.AUTO (default)

    • commit이나 쿼리 실행할 때 플러시
  2. @FlushModeType.COMMIT

    • commit할 때만 플러시

종료

영속성 컨텍스트를 종료하려면 EntityManager의 close 메소드를 호출한다.

em.close();

병합

준영속 상태의 데이터는 병합 기능을 사용하여 다시 영속 상태로 돌릴 수 있다.

SomeEntity entity = em.find(key);
em.detach(entity);
em.merge(entity);
저작자표시 비영리 (새창열림)

'Java > JPA' 카테고리의 다른 글

JPA 사용 시 주의할 점  (1) 2021.07.22
[JPA] 다양한 연관관계 매핑  (0) 2020.04.07
[JPA] 연관관계 매핑 기초  (1) 2020.02.26
[JPA] 엔티티 매핑  (0) 2020.02.22
  1. Entity Manager 생성
  2. 영속성 컨텍스트 (Persistence Context)
  3. 생명 주기
  4. 플러시 (flush)
  5. 종료
  6. 병합
'Java/JPA' 카테고리의 다른 글
  • JPA 사용 시 주의할 점
  • [JPA] 다양한 연관관계 매핑
  • [JPA] 연관관계 매핑 기초
  • [JPA] 엔티티 매핑
감동이중요해
감동이중요해
https://github.com/dhmin5693 dhmin5693@naver.com
감동이중요해
티끌모아 산을 쌓아보자
감동이중요해
전체
오늘
어제
  • 분류 전체보기 (111)
    • 알고리즘 (35)
    • Infra & Dev tools (10)
      • Git (2)
      • Cloud platform (5)
      • Mac, Linux (3)
    • BigData (1)
    • IT 도서 (11)
      • Clean Code (8)
    • Java (36)
      • Spring framework (19)
      • JPA (5)
      • Domain Driven Design (3)
    • Database (2)
      • oracle (1)
      • mysql (0)
    • Computer Science (7)
      • 운영체제 (7)
    • 기타 (9)
      • 크롤링(파이썬) (1)
      • 회고 (4)
      • Career (0)

블로그 메뉴

  • 홈
  • 태그
  • 미디어로그
  • 위치로그
  • 방명록

공지사항

  • About me

인기 글

태그

  • JPA
  • Linux
  • 운영체제
  • 알고리즘
  • Mac
  • 영속상태
  • Spring
  • 회고
  • 영속
  • 프로세스
  • Database
  • AWS
  • Clean Code
  • Java
  • DDD
  • 우아한테크캠프2기
  • Stream
  • 메모리
  • 블라인드공채
  • bean

최근 댓글

최근 글

hELLO · Designed By 정상우.v4.2.2
감동이중요해
[JPA] EntityManager, 영속성 컨텍스트
상단으로

티스토리툴바

개인정보

  • 티스토리 홈
  • 포럼
  • 로그인

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.