업데이트:

3 분 소요

Persistence Context, 영속성 컨텍스트

  • JPA의 핵심 요소
  • 엔티티를 영속화(영구 저장, Persistence Context내에서 관리)하는 환경이라는 의미
  • 엔티티를 Persistence Context에 보관하고 관리한다.

특징

  • 식별자
    영속성 컨텍스트는 key-value로 엔티티를 관리하기 때문에 식별자 값을 반드시 가져야한다.

  • 영속성 컨텍스트와 DB
    JPA는 트랜잭션을 커밋하는 순간 영속성 컨텍스트에 새로 저장된 엔티티를 DB에 반영한다.
    flush()를 통해 영속성 컨텍스트 내의 변경 사항을 DB와 동기화(변경 사항을 DB에 적용) 한다.

  • 1차 캐시

    흐름
    1. 최조 조회시 1차 캐시에 엔티티는 존재하지 않는다.
    2. save() 가 호출되면 엔티티를 1차 캐시와 DB에 보관한다.
    3. 1차 캐시에 보관된 결과를 반환한다.
    4. 같은 엔티티가 조회됐을 때 1차 캐시에 같은 엔티티가 있다면 데이터베이스를 조회하지 않고 1차캐시의 엔티티를 그대로 반환한다.

    • 영속성 컨텍스트 내부에 엔티티를 보관하는 장소
    • key/value 형태를 통해 성능을 크게 높여주지는 않지만, JPA의 동작 메커니즘(변경감지 등)을 가능하게 한다.
    • 같은 엔티티에 대한 객체의 동일성을 보장한다(a == b).
    • 트랜잭션 단위로 작동되며 한 트랜잭션 단위에서만 유효하다.

  • 객체의 동일성 보장
    1차 캐시를 이용함으로써 동일성을 보장받을 수 있다.

  • 트랜잭션을 지원하는 쓰기 지연
    SQL 버퍼에 쿼리를 담은 후, 영속성 컨텍스트의 명령에 따라 DB에 전송되기 때문에 한 번의 INSERT만 발생한다. 이는 DB와의 통신 회수를 줄여주며 성능상 이점을 가져다준다.

  • 변경 감지
    1차 캐시에 DB에서 처음 불러온 엔티티의 스냅샷(JPA는 엔티티를 영속성 컨텍스트에 보관할 때 최초 상태를 복사해 저장하며 이를 스냅샷이라고 한다.)을 저장하고 현재 내용과 차이점이 있다면 UPDATE SQL을 자동으로 수행한다.

  • 지연로딩
    엔티티 조회 시점이 아닌 엔티티 내 연관관계를 참조할 때 해당 연관관계에 대한 SQL이 질의되는 기능
    불필요한 조인 처리를 해 연관관계에 있는 데이터까지 한 번에 조회하지 않기 때문에 동작 부담을 줄일 수 있다.

Entity

Entity는 RDB의 Table과 매핑되는 객체이다.

  • @Entity 로 엔티티임을 명시할 수 있다
  • @Table(name = ?) 을 통해 RDB에 저장될 테이블명을 명시할 수 있다. 지정해주지 않을 경우 Class 명을 따라간다.
  • @Id 를 통해 Primary Key를 명시해줄 수 있다.

생명주기


lifecycle.png

  • 영속 (managed)

    영속성 컨텍스트에 저장된 상태

  • 비영속 (new / transient)

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

  • 준영속 (detached)

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

    • 특징
      • 비영속 상태와 근사

        영속성 컨텍스트가 관리하지 않기 때문에 제공하는 어떤 기능도 동작하지 않음

      • 식별값 보유

        비영속 상태에서는 식별값이 없을 수 있으나 영속 상태 였던 준영속 상태는 식별값을 보유

      • 지연 로딩 불가

        영속성 컨텍스트가 관리하지 않는 상태이기 때문에 지연 로딩 불가

  • 삭제 (removed)

    삭제된 상태


1. 객체가 Entity Manager가 호출한 persist()에 의해 영속화된다.

2. 영속화된 객체는 Persistence Context에 의해 관리되며 이는 (detach()/clear()/close(),remove())에 따라 준영속, 비영속 상태로 바뀌게 된다.

2.1.
detach(): Persistence Context에서 더이상 해당 엔티티를 관리하지 않는다. (식별자는 존재한다.)
clear() : 모든 엔티티를 더이상 관리하지 않는다.
close() : 모든 엔티티를 더이상 관리하지 않고 Persistence Context를 종료시킨다.

2.1.1
준영속 상태의 엔티티는 merge()를 통해 다시 영속되어질 수 있다.

2.1.2
비영속 상태의 엔티티는 persist()를 통해 다시 영속되어질 수 있다. 비영속 상태에서 flush()가 실행되면 DB와 동기화하여 DB내의 데이터를 삭제한다.

3.
영속화된 객체는 flush()를 통해서 DB와 동기화를 시작한다.

EntityManager

  • EntityManager는 엔티티에 CRUD 작업과 더불어 엔티티와 관련된 모든 일을 처리한다.
  • 멀티 스레드 환경에서 안전하지 않다. 따라서 여러 Thread에서 동시 접근할 경우 동시성 이슈가 발생할 수 있다.
  • 트랜잭션을 시작할 때 커넥션을 획득한다.

Entity Manager Factory

  • 엔티티를 관리하는 EntityManager를 생산하는 공장
  • Thread Safe(멀티 스레드 환경에서도 안전하다.)

Entity Mapping

데이터 베이스 스키마 생성

JPA와 hibernate를 이용하면 DB스키마(DDL)를 자동으로 생성해줄 수 있다.

spring:
  jpa:
    hibernate:
      ddl-auto: create-drop
                    //create
                    //update
                    //validate
                    //none

ddl-auto의 옵션으로는 위의 예시와 같이 설정할 수 있다.

  • create : 기존 테이블을 삭제하고 새로 테이블을 생성한다. (DROP + CREATE)
  • create-drop : 어플리케이션 종료시 생성한 DDL을 제거한다. (DROP + CREATE + DROP)
  • update: 테이블, 엔티티 매핑 정보를 비교해 변경사항을 수정한다.
  • validate: 테이블, 엔티티 매핑정보를 비교해서 차이가 있으면 어플리케이션을 실행하지 않는다.
  • none: 자동 생성 기능을 생성하지 않는다.

DDL 옵션

Entity 클래스 내에서 설정할 수 있는 DDL 옵션은 다음과 같다.

굳이 사용하지 않아도 되지만, 직접 개발하지 않은 개발자가 Entity를 확인함으로써 어떻게 구성되어있는지 가시적으로 표현함으로써 권장된다.

Class level


  • @Entity
    • name: 엔티티의 이름을 명시할 수 있다.
  • @Table
    • name :테이블의 이름을 명시할 수 있다.

Field level


  • @Column: 영속화된 엔티티나 속성에 대해 매핑된 컬럼을 특정할 수 있다.
    • 옵션
      • columnDefinition : 컬럼에 대한 DDL을 생설할 때 사용된 SQL fragment를 명시할 수 있다.
      • insertable : 엔티티를 저장할 때 필드도 함께 저장한다. false일 경우 일기 전용으로 사용한다.
      • length : 컬럼의 길이를 명시할 수 있다.
      • name : 컬럼의 이름을 명시할 수 있다.
      • nullable : DB의 컬럼에 null값이 들어갈 수 있는지 명시할 수 있다.
      • precision : 10진수 컬럼으로 명시할 수 있다.
      • scale: 10진수 컬럼에 대한 범위를 명시할 수 있다.
      • table: 해당 컬럼을 포함하는 테이블의 이름을 명시할 수 있다.
      • unique : 해당 컬럼이 unique 한 key인지 명시할 수 있다.
      • updatable : 엔티티를 수정할 때 필드도 함께 저장한다. false일 경우 일기 전용으로 사용한다.
  • @Id: 엔티티의 Primary key를 특정할 수 있다.
  • @GeneratedValue: Primary key의 생성 전략을 제공할 수 있다.
    • 옵션
      • strategy: 생성 전략
        • GenerationType.Auto : persistence provider가 특정 DB에 대한 적절한 전략을 선택할 수 있게 한다.
        • GenerationType.IDENTITY: 기본키 생성을 데이터베이스에 위임한다. persist()시점에 INSERT 쿼리가 수행된다.
        • GenerationType.SEQUENCE : DB가 자동으로 숫자를 생성한다.
        • GenerationType.TABLE: 키 생성 전용 테이블을 하나 만들어서 데이터베이스 시퀀스를 흉내내는 전략
        • @GeneratedValue를 입력하지 않을경우 영속화 전에 애플리케이션에 직접 값을 할당한다.
      • generator: primary key 제너레이터의 이름

Ref

https://velog.io/@bread_dd/JPA는-왜-지연-로딩을-사용할까

https://logical-code.tistory.com/140

댓글남기기