반응형
- JPA 에서 가장 중요한 2가지
- 객체와 관계형 데이터 베이스를 어떻게 매핑하나
- 영속성 컨텍스트 (JPA 가 내부적으로 어떻게 동작하나)
1. 영속성 컨텍스트란?
- 'Entity를 영구 저장하는 환경’이라는 뜻
- EntityManager.persist(entity);
- EntityManager를 통해 영속성 컨텍스트에 접근.
2. Entity 의 생명주기
- 비영속(new/transient) : 영속성 컨텍스트와 전혀 관계가 없는 새로운 상태
- 영속(managed) : 영속성 컨텍스트에 관리되는 상태 ((em.persist(member)))
- 준영속(detached) : 영속성 컨텍스트에 저장되었다가 분리된 상태 (em.detach(member))
- 삭제 (removed) : 삭제된 상태
*영속상태가 되었다고 해서 바로 데이터베이스에 쿼리가 생기는 것은 아님.
3. PersistenceContext의 이점
- 정리 : 1차 캐시 / 동일성 보장 / 트랜잭션을 지원하는 쓰기 지연 / Dirty checking (변경 사항 저장) / 지연 로딩 (Lazy loading)
1. 1차 캐시
- persist 를 통해 관리하게 되거나, 데이터베이스에서 조회하고 나면 그 결과를 영속성 컨텍스트 내부의 1차 캐시에 저장한다.
- pk @id 와 객체를 저장한다.
- 보통 트랜잭션 단위로 entityManager 가 생성되고 사용된 후 삭제되기 때문에, 이런 1차캐시는 한 트랜잭션 내로만 의미가 있고 성능상 이점이 많지는 않다.
(한 트랜잭션 마다 1차 캐시가 존재. 고객 10명이 연결되었다면 10명 모두 다른 1차 캐시 사용. 이 매커니즘 상의 이점이 있는 것이라고 보면 됨.)
2. 영속성 엔티티의 동일성 보장
- 컬렉션에 저장한 객체의 레퍼런스 비교 처럼 비교 가능. - 자세히 이야기하면 - 1차 캐시로 반복 가능한 읽기(REPEATABLE READ) 등급의 트랜잭션 격리 수준을 데이터베이스가 아닌 애플리케이션 차원에서 제공 - 1차 캐시에서 인스턴스를 보관하고 있다가 요청 시 그 인스턴스를 제공하기 때문에 가능한 일.
3. 트랜잭션을 지원하는 쓰기 지연
- persist 시에는 DB까지 저장하지 않고 1차 캐시에 엔티티 저장, 쓰기 지연 SQL 저장소에 sql문에 저장해두었다가, 트랜잭션을 커밋시에 저장해둔 sql문을 db에 날린다.
- sql문을 바로 보내지 않는 대신 최적화가 가능하다 : 커넥션 한번에 여러개의 쿼리를 날릴 수 있는. (배치 쿼리)
4. 엔티티 수정 변경 감지
- 이렇게만 해도, 데이터베이스 내부의 내용이 변경된다.
- dirty checking
- 커밋을 하면 내부적으로 flush() 가 호출됨.
- entity와 스냅샷을 비교.
- 변경사항이 있다면 update 쿼리문을 날린다.
4. Flush
- 영속성 컨텍스트의 변경 내용을 데이터베이스에 반영하는.
- flush가 호출되면
-
- 1차 캐시 내용과 비교해서 변경을 감지한 경우 updqte 쿼리문을 쓰기 지연 sql 저장소에 저장.
- 저장해둔 쓰기 지연 sql 저장소의 sql문을 실행. (등록, 수정, 삭제 쿼리들)
-
- flush를 호출하는 방법
-
- em.flush()
- 트랜잭션 커밋 (쟈동 flush 호출)
- JPQL 쿼리 실행 (자동 flush 호출)
(flush 되었다고 1차 캐시 내용이 사라지거나 하는 것은 아님.
단지 작업환경의 영속성 컨텍스트의 변경내용과 데이터베이스와 동기화작업이라고 보면 될듯)
(트랜잭션이라는 작업 단위가 중요: 커밋 직전에만 동기화가 되면 되는 것이다.)
-
- 원래는 === 이후에 발생했던 쿼리가 그 이전에 날라가는 것을 볼 수 있다.
(JPQL 쿼리 실행 시 자동 호출되는 이유:
다음과 같은 코드에서 JPQL을 실행할 때 애초에 데이터베이스에 반영된 memberA,. B, C가 없으므로 문제가 될 수 있기 때문에, 기본적으로 쌓아둔 sql 저장소의 쿼리 들을 실행한 후(flush 호출 후) JPQL 을 실행하도록 한다. )
- 플러시 모드 옵션
em.setFlushMode(FlushModeType.COMMIT)
- FlushModeType.AUTO
- 커밋이나 쿼리를 실행할 때 플러시 (기본 값.)
- FlushModeType.COMMIT
5. 준영속 상태
- 영속 상태의 엔티티가 영속성 컨텍스트에서 분리된 상태. (정확히 어떤 상태인지 예시는 추후 설명.)
- 영속성 컨텍스트가 제공하는 기능은 사용못함.
- 준영속상태가 되는 방법
- em.detach(entity)
- 커밋 직전에 select 쿼리만 일어날 뿐, setName으로 인한 변경사항을 담은 update 쿼리는 일어나지 않는다. (detach 를 통해서 영속성 컨텍스트에서 관리하던 1차 캐시에서 제거되었으므로 변경사항을 감지할 수 없음.)
- em.detach(entity)
- em.clear()
- 영속성 컨텍스트를 완전히 초기화.
- find 하고 나서 clear() 하고나면, 1차 캐시에서 지워졌기 때문에 그 다음 find에서 다시 select를 해야한다.
- 총 2번의 select 쿼리가 일어나는.
- 영속성 컨텍스트를 완전히 초기화.
- em.close()
- 영속성 컨텍스트를 종료
반응형
'개발 > java' 카테고리의 다른 글
[Spring - JPA] 4. 엔티티 매핑 (0) | 2024.03.16 |
---|---|
Spring 에서 configuration 을 다루는 방법 - @Value vs @ConfigurationProperties (2) | 2024.02.26 |
[Spring - JPA] 2. JPA 개요 (1) | 2024.02.18 |
[Spring - JPA] 1. JPA 소개 (1) | 2024.02.03 |
[Spring - DB] 1. JDBC 이해 (2) | 2024.01.07 |