JPA가 컬렉션에 대해 변경 감지 이후 어떻게 SQL을 처리하는지 알기 전 책으로 읽었던 영속성 컨텍스트를 복습해보자.
JPA에서 가장 중요한건 객체와 관계형 데이터베이스 매핑하는 것과 영속성 컨텍스트이다.
영속성 컨텍스트는 엔티티를 영구 저장하는 환경이라는 뜻을 가지고 있다.
영속성 컨텍스트는 논리적인 개념으로 실제 JPA를 처음 사용하게 될 때는 엔티티 매니저 팩토리에서 엔티티 매니저를 사용하여 다음과 같이 사용하게 된다.
EntityManger.persist(entity)
이는 실제 DB에 쿼리를 전송하는 것은 아니고 실제 DB에 쿼리를 전송하는 행위는 JPA에게 위임하게 되는데 JPA가 내부적으로 관리하게 되는 저장소라고 생각하면 될 듯하다.
하지만 persist()를 호출했다고 즉시 데이터베이스에 반영되지는 않는다. 반영하기 위해선 트랜잭션의 커밋한 이후 반영된다.
엔티티의 생명주기
엔티티는 생명 주기가 존재한다.
- 비영속
비영속 상태는 엔티티를 생성만 한 상태로 영속 컨텍스트에 저장하지 않은 상태이다. - 영속
엔티티매니저에 persist를 통해 엔티티를 저장한 상태를 말한다. - 준영속
detach를 통해 영속성 컨텍스트에서 엔티티를 더 이상 관리하지 않도록 할 수 있다. - 삭제
remove()를 통해 데이터베이스에 지우는 것이다.
영속성 컨텍스트를 통해 얻을 수 있는 이점
쉽게 말해 영속성 컨텍스트는 하나의 어댑터역할을 진행하는 것 같다.
다양한 기능을 포함하고 있고 그 기능을 적용한 다음 실제 데이터베이스에 데이터를 적용하기 때문이다.
1차 캐시
영속성 컨텍스트는 내부에 1차 캐시를 가지고 있다.
데이터베이스 PK로 매핑한 것이 @Id, 값은 엔티티 자체이다.
이는 하나의 트랜잭션에서 동일 엔티티를 조회한다면 조회 성능에 이득을 볼 수 있다.
다만 영속 컨텍스트는 트랜잭션 종료 시 사라진다. 그렇기 때문에 아주 복잡한 비즈니스 로직에서만 영향을 받을 수 있다.
영속 엔티티의 동일성 보장
1차 캐시로 반복 가능한 읽기 등급의 트랜잭션 격리 수준을 데이터베이스가 아닌 애플리케이션 차원에서 제공한다.
이는 트랜잭션이 동일한 데이터를 다시 읽는 경우 이전에 읽은 데이터가 변경되지 않은 채로 데이터베이스에 저장돼 있음을 보장한다는 것을 의미하고 이를 트랜잭션 격리 수준을 설정하는 것이 아닌 영속 컨텍스트의 기능을 통해 얻는다는 것 같다.
쓰기 지연
쓰기 지연 SQL 저장소라는 것이 영속 컨텍스트에 존재한다. persist()를 통해 엔티티를 저장할 때 1차 캐시에 저장한 후
엔티티를 분석하여 알맞은 데이터베이스 쿼리를 생성해서 쓰기 지연 SQL 저장소에 저장한다.
이후 트랜잭션이 커밋되었을 때 쿼리를 데이터베이스에 전송한다.
이는 최적화에 대한 여지를 준다. hibernate.jdbc.batch_size를 조절하면 size 만큼 모아서 보내기 때문에 네트워크의 이점을 얻을 수 있다.
변경 감지
트랜잭션 커밋 시점에 엔티티와 스냅샷을 비교하여 변경된 부분을 확인하여 쓰기 지연 SQL 저장소를 flush()하여 실제 DB에 적용한다.
변경 감지와 병합에 대해선 뒤편에서 다루었다!
https://chinggin.tistory.com/717
플러시
플러시는 영속성 컨텍스트의 변경내용을 데이터베이스에 반영하는 것을 말한다.
이는 데이터베이스와 동기화하는 것이지 영속성 컨텍스트를 비우는 것이 아니다.
플러시가 발생하면 변경 감지, 수정된 엔티티 쓰기 지연 SQL 저장소에 등록, SQL 저장소에 저장된 쿼리를 데이터베이스에 전송한다.
플러시는 다음과 같은 상황에 발생한다.
- em.flush() 직접 호출
- 트랜잭션이 커밋되는 시점
- JPQL 쿼리 실행
JPA는 기본적으로 데이터를 동기화하고 동시성에 대한 것은 트랜잭션에 위임해서 사용한다.
이게 가능한 것은 아마 트랜잭션 관련 프록시를 통해 작업에 위임하고 이러한 모든 작업들은 트랜잭션이 커밋되기 이전에만 실행하면 되기 때문일 것이다.
'데이터 접근 기술 > JPA' 카테고리의 다른 글
나는 지금 JPQL이 필요하다! (0) | 2022.10.26 |
---|---|
주말 정리 (0) | 2022.10.24 |
Entity의 변경을 JPA에서 처리하는 방법 (0) | 2022.10.23 |
JPA 공부하기 전 (0) | 2022.10.22 |
[JPA] 공부하면서 나중에 찾아볼 것들 (0) | 2021.04.17 |
댓글