일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
Tags
- CKA
- Oracle
- CI
- builder-pattern
- ORM
- vuejs
- SpringMVC
- k8s
- 뷰
- IntelliJ
- JPA
- hibernate
- CI/CD
- Spring
- 해시맵
- programmers
- java
- map
- dabase
- DevOps
- 프로그래머스
- Kubernetes
- 코딩테스트연습
- Di
- docker
- 알고리즘
- cd
- 자바
- superBuilder
- Vue
Archives
- Today
- Total
문홍의 공부장
[Java JPA] JPA 영속성 컨텍스트 개념 정리 본문
반응형
JPA 영속성 컨텍스트
- 영속성: 프로그램이 종료되어도 사라지지 않는 데이터의 특성.
- 영속성 컨텍스트: 엔티티를 영구 저장하는 환경.
개념
- 애플리케이션과 데이터베이스 사이에서, 객체를 보관하는 논리적 개념 (가상의 DB 역할)
- 영속성 컨텍스트는 직접 접근이 불가하며, 엔티티 매니저
EntityManager
를 통해서 접근 가능하다. EntityManager
를 통해 엔티티를 저장/조회 시, 엔티티 매니저는 영속성 컨텍스트에 엔티티를 보관하고 관리한다. (em.persist()
)- 트랜잭션을 커밋하는 시점에 영속성 컨텍스트의 내용이 테이블에 반영된다. (
em.flush()
)
엔티티의 생명주기
- 비영속(new/transient)
- 엔티티를 생성했지만 아직 영속성 컨텍스트에 저장하지 않은 상태
- 영속(managed)
- 엔티티 매니저를 통해 엔티티를 영속성 컨텍스트에 저장한 상태. (
em.persist()
) - 영속성 컨텍스트에 의해 관리되며, 아직 DB에 저장되지는 않음.
- 엔티티 매니저를 통해 엔티티를 영속성 컨텍스트에 저장한 상태. (
- 준영속(detached)
- 영속성 컨텍스트에 저장되었다가 분리된 상태 (
em.detach()
) - 영속성 컨텍스트가 관리하던 영속 상태의 엔티티 더이상 관리하지 않음
- 영속성 컨텍스트에 저장되었다가 분리된 상태 (
- 삭제(removed)
- 엔티티를 영속성 컨텍스트와 DB에셔 삭제 (
em.remove()
)
- 엔티티를 영속성 컨텍스트와 DB에셔 삭제 (
특징
- 영속 상태는 반드시 식별자 값(
@Id
)을 지닌다. - 트랜잭션 커밋 시 영속성 컨텍스트에 저장된 내용을 데이터베이스에 자동으로 반영(동기화) 한다. (
em.flush()
)
장점
1차 캐시
영속성 컨텍스트 내부에 존재하는 캐시. 영속 상태의 엔티티를 1차 캐시에 저장한다. (key:value = 식별자값:엔티티 인스턴스)
// em.find(엔티티 클래스 타입, 식별자 값);
Member member = em.find(Member.class, "member1");
[조회의 흐름]
- 1차 캐시에서 엔티티를 찾는다
- 있으면 메모리에 있는 1차 캐시에서 엔티티를 조회한다.
- 없으면 데이터베이스에서 조회한다.
- 조회한 데이터로 엔티티를 생성해 1차 캐시에 저장한다. (엔티티를 영속상태로 만든다)
- 조회한 엔티티를 반환한다.
즉, 영속성 컨텍스트의 1차 캐시에 존재한다면 데이터베이스까지 가지 않고 바로 엔티티를 조회할 수 있다.
동일성 보장
영속성 컨텍스트는 엔티티의 동일성을 보장한다.
Member a = em.find(Member.class, "member1");
Member b = em.find(Member.class, "member1");
System.out.print(a==b) // true
SQL mapper 를 사용하여 결과를 가져와 객체 a, b 에 담았다면, 두 객체의 주소값이 다르기 때문에 a==b 는 false 가 나왔을 것이다.
하지만 JPA 를 사용할 경우 em.find()
를 반복 호출하여도 영속성 컨텍스트의 1차 캐시에 보관된 같은 인스턴스를 반환한다.
이런 이유로 영속 엔티티의 동일성을 보장할 수 있다.
트랙잭션을 지원하는 쓰기 지연
em.persist(member1);
em.persist(member2);
엔티티 매니저는 트랜잭션을 커밋하기 직전까지 내부 쿼리 저장소에 INSERT SQL을 모아두고, 트랜잭션을 커밋할 때 모아둔 쿼리를 DB에 보낸다.
이것을 트랜잭션을 지원하는 쓰기 지연이라 한다.
변경 감지 (Dirty checking)
엔티티를 조회해서 데이터를 변경하면, JPA는 변경 내용을 감지하여 update SQL 를 생성한다.
Member member = em.find(Member.class, 10L);
member.setName("changedName");
transaction.commit(); // execute update query
[변경감지의 흐름]
- 트랙잭션을 커밋하면 엔티티 매니저 내부에서 먼저 플러시가 호출된다.
- 엔티티와 1차 캐시 내의 스냅샷을 비교하여 변경된 엔티티를 찾는다.
- 변경된 엔티티가 있으면 UPDATE SQL 를 생성해서 쓰기 지연 SQL 저장소에 저장한다.
- commit 이 되면 쓰기 지연 저장소의 SQL을 플러시한다.
지연 로딩 (Lazy Loading)
연관관계 매핑되어 있는 엔티티 조회 시, 프록시를 반환함으로써 쿼리를 진짜 필요할 때 실행하도록 하는 기능
플러시 (flush) ?
- 영속성 컨텍스트의 변경 내용을 DB 에 반영
플러시가 발생하면
- 변경 감지
- 수정된 엔티티 쓰기 지연 SQL 저장소에 등록
- 쓰기 지연 SQL 저장소의 쿼리를 DB 에 전송
플러시하는 방법
- 트랜잭션 커밋 시 자동 호출
- em.flush()
- JPQL 쿼리 실행
Reference.
반응형
'개발 > Java' 카테고리의 다른 글
[Spring] Spring AOP 이해하기 (2) - @Transactional 의 동작 원리 (0) | 2023.04.23 |
---|---|
[Spring] Spring AOP 이해하기 (1) - Spring AOP 의 개념 (0) | 2023.04.23 |
[Java JPA] JPA 개념 정리 (0) | 2022.04.22 |
[Java] Division by Zero in Java: Exception, Infinity, or Not a Number (0) | 2022.01.07 |
[Java] ObjectMapper를 사용하여 Object 를 Map 으로 변경하기 (0) | 2022.01.07 |