ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 영속성 컨텍스트
    🌱 spring 2022. 10. 11. 00:49

    영속성 컨텍스트 ❓


    영속성 컨텍스트란 엔티티를 관리하는 영역으로, key-value 형태로 엔티티를 관리한다.

    • key는 엔티티의 식별자 값이고 value는 엔티티 그 자체
    • 따라서 식별자 값이 꼭 필요하다.

    특징

    • 엔티티 매니저를 생성할 때 하나 만들어진다.
    • 엔티티 매니저를 통해서 영속성 컨텍스트에 접근하고 관리할 수 있다.

    엔티티 생명주기

    • 비영속 : 영속성 컨텍스트와 관계가 없는 새로운 상태
    • 영속 : 영속성 컨텍스트에 저장된 상태
    • 준영속 : 영속성 컨텍스트에 저장되었다가 분리된 상태
    • 삭제 : 삭제된 상태

    비영속

    • 엔티티 객체를 생성했지만 아직 영속성 컨텍스트에 저장하지 않은 상태

    영속

    • 엔티티 매니저를 통해서 엔티티를 영속성 컨텍스트에 저장한 상태
    • 영속성 컨텍스트에 의해 관리가 된다.

    준영속

    • 영속성 컨텍스트가 관리하던 영속상태의 엔티티 더 이상 관리하지 않으면 준영속 상태가 된다.
    • em.detach()

    준영속 상태의 특징

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

    삭제

    • 엔티티를 영속성 컨텍스트와 데이터베이스에서 삭제한다.

    flush(플러시)

    JPA는 트랜잭션 커밋 시 영속성 컨텍스트에 새로 저장된 엔티티를 DB에 반영한다.

    이때, 영속성 컨텍스트의 변경내용을 데이터베이스에 반영하는 것을 플러시 라고 한다.

    • 실제로는 플러시 다음에 커밋이 일어난다.

    주의점

    • 플러시로 인해 영속성 컨텍스트가 비워지는 것은 아니다.
    • 플러시는 영속성 컨텍스트의 변경 사항들과 DB의 상태를 맞추는 작업으로 영속성 컨텍스트의 변경 내용을 DB에 동기화한다.

    동작

    1. 플러시를 한다
    2. dirty checking(변경 감지) 이 일어난다
    3. 쓰기 지연 저장소 가 비워진다
    • 1차 캐시는 그대로 유지 된다.

    영속성 컨텍스트의 장점 ❗


    1차 캐시

    영속성 컨텍스트 내부에 엔티티를 보관하는 저장소

    • 일반적으로 트랜잭션을 시작하고 종료할 때까지만 1차 캐시가 유효하다.

    조회시 1차 캐시에 데이터가 있다면 가져오고 없다면 데이터베이스에 데이터를 요청한 후, 데이터를 다음에 재 사용할 수 있도록 1차 캐시에 저장한다.

    • 따라서, 조회한 데이터를 메모리에 캐싱해 두어 DB 접근횟수를 줄여 성능을 개선한다.

    동작방식

    1. 최초 조회시 1차 캐시에 엔티티가 없다.
    2. DB에서 엔티티를 조회한다.
    3. 엔티티를 1차 캐시에 보관한다
    4. 1차 캐시에 보관된 결과를 반환한다
    5. 이후, 같은 엔티티 조회시 1차 캐시에 엔티티가 있으므로 DB에 접근하지 않고 1차 캐시의 엔티티를 그대로 반환한다.

    1차 캐시는 객체의 동일성 (a == b)을 보장한다.

    1차 캐시가 비워지는 시점 = 트랜잭션 종료 시점

    2차 캐시

    출처 : 자바 ORM 표준 JPA 프로그래밍 (저자 : 김영한)

    하이버네이트를 포함한 대부분의 JPA 구현체들은 애플리케이션 범위의 캐시를 지원한다

    ⇒ 2차 캐시

    2차 캐시는 동시성을 극대화하기 위해 캐시 한 객체를 직접 반환하지 않고 복사본을 만들어서 반환한다.

    • 애플리케이션 범위의 캐시로, 공유 캐시
    • 따라서, 애플리케이션을 종료할 때 까지 캐시가 유지된다.

    동작 방식

    1. 영속성 컨텍스트는 엔티티가 필요하면 2차 캐시를 조회한다
    2. 2차 캐시에 엔티티가 없으면 데이터베이스를 조회한다
    3. 조회한 결과를 2차 캐시에 보관한다
    4. 2차 캐시는 자신이 보관하고 있는 엔티티를 복사해서 반환한다

    2차 캐시는 DB 기본키를 기준으로 캐시하지만 영속성 컨텍스트가 다르면 객체 동일성 (a==b)을 보장하지 않다.

    복사본을 만들어 반환하는 이유❓

    • 캐시 한 객체를 그대로 반환하면 여러 곳에서 같은 객체를 동시에 수정하는 동시성 문제가 발생할 수 있다.
    • 이를 해결하기 위해서 객체에 락을 걸어야 하는데 이러면 동시성이 떨어질 수 있다.
    • 따라서 2차 캐시는 원본 대신에 복사본을 반환한다.
    • 2차 캐시를 잘 사용하면 1차 캐시의 동시성 문제를 해결하고 애플리케이션 조회 성능을 올릴 수 있다.

    동일성 보장

    동일성이 보장되는 이유는 1차 캐시 때문이다.

    1차 캐시로 REPEATABLE READ 등급의 트랜잭션 격리 수준을 데이터베이스가 아닌 애플리케이션 차원에서 제공받을 수 있다.

    REPEATABLE READ

    • 동일한 트랜잭션 내에서 동일한 결과를 보여주는 트랜잭션 격리 수준
    • 다른 트랜잭션에서 데이터가 변경되었을 경우 다른 결과가 보여지는 것을 해결한 격리 수준

    쓰기 지연

    영속성 컨텍스트에 변경이 발생했을 때, 바로 데이터베이스에 쿼리를 보내지 않고 SQL 쿼리를 쓰기 지연 저장소(버퍼)에 모아 놨다가, 영속성 컨텍스트가 flush하는 시점에 모아둔 SQL 쿼리를 데이터베이스를 보내는 기능

    변경 감지 (dirty checking)

    영속성 컨텍스트를 이용하면 update 로직을 따로 실행하지 않아도 된다.

    • 엔티티가 변경됐을 뿐인데 update 쿼리가 실행된다

    왜 dirty checking이 일어날까?

    JPA는 엔티티 조회시 해당 엔티티를 조회 상태 그대로 1차 캐시에 스냅샷을 만들어 놓는다.

    • 그리고 트랜잭션 커밋시점( 정확히는 flush 되는 시점 )에 스냅샷과 엔티티 객체를 비교해 변경이 되었으면 update 쿼리를 쓰기 지연 저장소에 생성하고 DB에 반영한다.

    변경 감지는 영속성 컨텍스트가 관리하는 영속상태의 엔티티만 적용이 된다.

    지연 로딩(Lazy Loading)

    즉시 로딩(Eager Loading)

    특정 엔티티를 조회할 때 연관된 모든 엔티티를 같이 로딩하는 것.

    • 연관된 엔티티를 모두 가져온다는 장점이 있다.
    • 엔티티간의 관계가 복잡해질 수록 조인으로 인한 성능 저하가 생긴다.
    • ‘즉시 로딩’은불필요한 조인까지 포함해 처리하는 경우가 많아 ‘지연 로딩’ 사용을 권장한다.

    fetch

    JPA에서 연관관계 데이터를 어떻게 가져올 것인가?

    연관관계의 어노테이션 속성으로 ‘fetch’ 모드를 지정

     

    지연 로딩(Lazy Loading)

    가능한 객체의 초기화를 지연시키는데 사용

    실제 사용하는 시점에 데이터베이스에서 필요한 데이터를 가져온다.

    지연 로딩을 사용하면 실제 엔티티 객체 대신 가짜 객체가 필요하다 = 프록시 객체

    프록시 객체

    지연로딩 기능을 사용하기 위해 실제 엔티티 객체 대신 데이터베이스 조회를 지연할 수 있는 가짜 객체가 필요하다, 그것을 프록시 객체 라고 한다.

    프록시 기초

    JPA에서 식별자를 통해 엔티티를 조회할 때 조회를 미루고 싶다면 EntityManager.getReference() 를 사용한다

    이 메서드를 사용하면 JPA는 데이터베이스를 조회하지 않고 실제 엔티티를 생성하지 않는 대신 데이터 베이스 접근을 위임한 프록시 객체를 반환한다.

    • 실제 엔티티 조회시는 EntityManager.find() 를 사용

    프록시 초기화

    프록시 객체를 실제 데이터 값을 사용할 때 조회해서 실제 엔티티 객체를 생성한다.

     

    참고 자료

    https://docs.jboss.org/hibernate/orm/5.4/userguide/html_single/Hibernate_User_Guide.html

    https://velog.io/@neptunes032/JPA-영속성-컨텍스트란

    https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=62681446

    https://junghyungil.tistory.com/203

    https://devbksheen.tistory.com/entry/JPA-1차-캐시와-2차-캐시-소개

    https://zzang9ha.tistory.com/347

    '🌱 spring' 카테고리의 다른 글

    OSIV 🧐  (0) 2022.10.11
    JPA - N + 1 문제  (0) 2022.10.11
    JPA와 Hibernate, Spring data JPA  (0) 2022.10.10
    Spock 로 테스트 해보기  (0) 2022.10.06
    MVCC  (1) 2022.10.05

    댓글

Designed by Tistory.