-
[CS] JPA 영속성 컨텍스트CS 2023. 1. 6. 11:56728x90
영속성 컨텍스트란?
영속성 컨텍스트라고 하면, 엔티티를 영구 저장하는 환경 이라는 뜻이다
애플리케이션 ———- 영속성 컨텍스트( 가상의 디비 ) ————- 디비
이렇게, 애플리케이션과 디비 사이의 가상의 디비라고 생각하면 편하다.
엔티티 매니저를 통한 엔티티를 영속성 컨텍스트에 저장하는 방법
em.persist(member); // em 은 엔티티 매니저인데, 코드를 설명해보면, 엔티티 매니저로 member라는 엔티티를 저장한다!
영속성 컨텍스트 특징
영속성 컨텍스트의 식별자 값
영속성 컨텍스트는 엔티티를 식별자 값으로 구분한다. 따라서 영속 상태는 식별자 값이 반드시 있어야 한다.
영속성 컨텍스트와 디비 저장
JPA는 보통 트랜잭션을 커밋하는 순간 영속성 컨텍스트에 새로 저장된 엔티티를 데이터 베이스에 반영하는데 이를 flush라 한다.
영속성 컨텍스트가 엔티티 관리시 이점
- 1차 캐시
- 1차 캐시로 엔티티 조회시 1차캐시에 있는 데이터인지 먼저 체크하고 없을시에는 디비를 확인하는데, 1차캐시에 있다면 동일한 인스턴스이기에 동등성 뿐만 아니라 동일성도 보장하며 조회 성능 개선
- 동일성 보장
- 트랙잭션을 지원하는 쓰기 지연
- sql 변경마다 디비에 반영하지 않고 모아뒀다가 커밋시에 한번에 반영하면서 시간적 메모리적으로 낭비를 줄이고 성능을 개선
- 변경 감지
- 업데이트 쿼리를 갖지 않고, 스냅샷과 비교해서 코드의 번거로움과 성능 개선
- 지연 로딩
- 프록시 객체를 통해서 실제 사용까지 디비 조회를 미루어서 성능상 개선
엔티티 라이프 사이클
엔티티 라이프 사이클 - 비영속 : 영속성 컨텍스트와 관계가 없는 상태
- 영속 : 영속성 컨텍스트에 저장된 상태 ( 영속성 컨텍스트에 의해서 관리 받는 상태 )
- 준영속 : 영속성 컨텍스트에서 분리된 상태
- 삭제 : 삭제된 상태
비영속
엔티티 객체는 생성했지만, 영속성 컨텍스트에 저장하지 않은 상태
Member member = new Member()
영속
엔티티 매니저를 통해서 영속성 컨텍스트에 엔티티를 저장한 상태
em.persist(member);
준영속
영속성 컨텍스트에 의해서 더이상 엔티티가 관리되지 않는 상태
// 특정 엔티티를 영속성 컨텍스트에서 분리해 준영속 상태로 만든다. em.detach(member); // 영속성 콘텍스트를 비워도 관리되던 엔티티는 준영속 상태가 된다. em.claer(); // 영속성 콘텍스트를 종료해도 관리되던 엔티티는 준영속 상태가 된다. em.close();
다만, 우리가 체크할 점
- 준영속은 영속성 컨텍스트에 의해서 관리 받지 않기에 영속 상태에서 받을 수 있는 기능이 동작하지 않음
- 1차 캐시, 지연로딩, 더티 체킹 등
- 식별자 값은 갖음
삭제
엔티티를 영속성 컨텍스트와 디비에서 삭제
em.remove(member);
N+1 문제
→ 성능에 관한 문제인데, n개를 조회하는데 n개만큼 더 조회가 되어져서 성능상 이슈가 되는 문제를 말함
좀 더 구체적으로 말하면, 연관 관계가 설정된 엔티티를 조회할 경우에 조회된 데이터의 개수(n) 만큼 연관관계의 조회 쿼리가 추가로 발생해 데이터를 읽어오는 현상을 말함
발생 원인
JPA가 JPQL을 분석해서 SQL을 생성할 때 글로벌 패치 전략을 참고하지 않고 JPQL만을 사용할때 발생
- 글로벌 패치 전략이 EAGER(즉시 로딩)으로 한 경우
- 글로벌 패치 전략이 LAZY(지연 로딩)으로 한 경우에도 발생이 가능하다
- 지연 로딩에서는 N+1 문제가 발생하지 않는 것처럼 보였지만 막상 객체를 탐색하려고 하면 N+1 문제가 발생되어 N+1문제가 발생되는 시점만 즉시 로딩과 다를 뿐이다.
해결 방법
- Fetch join
- @EntityGraph
- Batch size
- 이 옵션은 정확히는 N+1 문제를 안 일어나게 하는 방법은 아니고 N+1 문제가 발생하더라도 그나마 성능을 최적화 시키는 방법이다.
방지 방법
- 글로벌 패치 전략이 LAZY(지연 로딩)을 사용하며, 성능 최적화가 필요한 경우는 Fetch 조인을 사용하고, 기본적으로 Batch Size는 100 이하로 설정한다.
참고
'CS' 카테고리의 다른 글
[CS] 동적 프록시 (0) 2023.01.07 [CS] 직렬화 (0) 2023.01.07 [CS] 스프링부트를 쓰는 이유와 자동설정 원리 (0) 2023.01.05 [CS] AOP (0) 2023.01.04 [CS] Bean (0) 2023.01.04 - 1차 캐시