반응형
EntityManagerFactory 와 EntityManager
- EntityManagerFactory : EntityManager 객체를 생성하는 클래스 -> 여러 쓰레드가 접속 가능
- EntityManagerFactory를 생성할 때 Connection Pool도 같이 생성함
- EntityManager : 실제 트랜젝션 이 작용하는 곳에서 DB에 CRUD 연산을 해주는 객체 -> 여러 쓰레드가 공유하면 동시성 문제 발생
- EntityManager가 생성되었지만, 실제 물리 DB와 연결할필요가 없으면 Connection Pool을 획득하지 않는다.
- EntityManager가 생성될 때 영속성 컨택스트를 같이 생성한다.(아래 참고)
영속성 컨택스트(Persistence Context)
정의 : 엔티티 객체를 영구적으로 정장하는 환경
특징
- 엔티티를 저장하거나, 조회 하게되면 영속성 컨택스트가 엔티티 객체를 저장
생명주기
비영속
- 정의 : 영속성컨택스트와 관련없는 상태를 의미
User user = new User();
user.setId("hello");
영속
- 정의 : 영속성 컨택스트가 저장한 상태(조회, 저장 후)
- find, JPQL를 사용해서 Entity객체를 조회하거나, persist를 통해서 객체를 저장한 Entity객체를 영속성 상태라고 말한다.
- 특징
- 식별자 값 존재 : @Id 가 붙은 필드 변수에 null이 아닌 값이 무조건 있어야 한다
- DB저장 시점 : EntityManger를 commit하는 순간 flush 라는 함수가 호출 되는데 그 때 persist된 객체를 DB에 저장하는 query를 날린다.
준영속
- 정의 : 영속성 컨택스트에 저장되었다가 분리된 상태
- 엔티티 객체가 영속성 컨택스트에서 불리된 상태(영속성 상태 -> 준영속)
- 종류
- em.detach(Entity class) : 특정 Entity만 준영속으로 변경 -> 쓰기 지연SQL, 변경 감지 정보를 전부 파기 한다
- em.clear() : 영속성 컨택스트를 다시 초기화 해서 모든 영속성이었던 Entity 객체를 준영속으로 변경
- em.close() : 영속성 컨택스트를 종료 해서 모든 영속성 컨택스트의 정보를 준영속 상태로 변경
- 특징
- 비영속에 가까움 : 1차 캐시, 변경 감지, 쓰기 지연 변경 모두 사용 안함
- 식별자 값이 있음 : 한번 영속 상태였기 때문에 Id는 존재
- 지연 로딩 불가
삭제
- 정의 : 삭제된 상태
영속성 컨택스트의 장점 및 특징
- 1차 캐시
- 정의 : 영속성 컨택스트 내부에 존재하는 캐시
- Map Entity 객체를 으로 관리
@Id
가 선언된 필드를 Key로 가짐- 동일한 트랜젝션에서 동일한 @Id를 가진 Entity 객체를 조회하게 된다면 처음에는 DB에 접근하지만, 두번 째는 1차 캐시에 존재한 객체를 가져온다.
- 1차 캐시에서 조회했을 때 없으면 DB에서 데이터 조회
- 영속 Entity 동일성 보장
- 동일한 객체를 반환하기 때문
- 동일성 : 실제 인스턴스 자체가 동일
==
연산결과 true - 동등성 : 실제 인스턴스는 다르나 내부 값이 동일(equals 함수로 정의 된 것)
- 동일성 : 실제 인스턴스 자체가 동일
- 지연 등록
- 트랜젝션을 commit하기 전에 까지 database에 엔티티 객체를
EntityManager
에 저장만 한다 - commit이 나오면 insert sql이 합쳐져서 한번에 나가게 한다.
- 지연 쓰기(Transaction wrtie-behind)
- Entity 객체를 1차 캐시에 집어 넣고 쓰기 지연 SQL 저장소에 저장
- commit시 자동으로 flush를 호출
- 중간에 update query가 존재할 경우 성능 최적화 가능
- 변경 감지
- 비즈니스 로직으로 인해서 다양한 update 쿼리 생성
- 영속성 컨택스트에 처음에 들어가면 스냅샷에 최초 상태를 복사한다
- 영속상태의 객체만 적용이 된다
- 마지막 commit을 날리면 스냅샷이랑 다른 컬럼이 존재하면 모든 column을 한번에 update한다
- 단점 : 전송량 증가
- 장점
- Application에서 수정 쿼리 재사용
- DB에서도 동일 쿼리가 존재하면 이전에 파싱한 쿼리를 재사용
- 동적으로 update쿼리 생성
- hibernate의 update SQL 생성전략인
@org.hibernate.annotations.DynamicUpdate
를 사용해야함
- hibernate의 update SQL 생성전략인
@Entity
@org.hibernate.annotations.DynamicUpdate
public class User {
// ,,,
}
- 지연 삭제
- commit(flush)가 호출 될 때 마지막에 삭제 sql이 날라가게 된다
- 지연 로딩(Lazy Loading)
- 처음에 참조한 연관 관계 Entity 객체를 DB에서 바로 가져오지 않고 Proxy 객체로 가지고 있다가 Proxy객체를 참조하면 실제 DB에서 데이터를 가져오는 것
- Trasaction 내부에 존재해야지 가능
Flush
- 정의 : 영속성 컨택스트의 변경 내용을 DB에 반영
- flush 를 한 후에도 영속성 컨택스트에 데이터는 남아있고, DB에 쿼리문으로 반영만 한 상태이다.
작동 과정
- (변경 감지)스냅샷과 수정된 Entity 를 찾아 수정 쿼리를 SQL저장소에 등록
- 쓰기 지연 SQL를 DB에 전송(등록, 수정, 삭제 쿼리)
flush 하는 방법
- 함수 직접 호출 :
entityManager.flush()
- 주로 사용하지 않음
- 트랙젝션 commit시 자동 호출
- commit 이 일어 나기전에 flush가 자동으로 호출
- JPQL 쿼리 실행 전에 flush 자동 호출
- criteria와 같은 객체 지향 쿼리를 호출할 때 플러시가 자동을 호출
- JPQL 호출 이전에 영속성 컨택스트에 존재하는 객체를 JPQL에서 조회할 수 있기 때문에 JPQL 호출 이전에 flush하고 다음에 JPQL을 호출 한다
병합(Merge)
- 정의 : 준영속 객체를 다시 영속성 객체로 변경하는 작업(준영속 객체를 새로운 영속성 객체로 반환해 주는 것)
실행 순서
- merge 호출
- 1차 캐시를 통해서 Entity객체 존재 여부 판단 -> 없으면 DB에서 조회해서 1차 캐시로 저장
- 새로 조회한 영속 Entity 객체에 merge에서 받아온 데이터를 하나씩 차례대로 넣어준다 -> 변경 감지 반영
- 새로 영속성 컨택스트에 존재하는 Entity객체를 반환
반응형
'JPA > ORM 표준 JPA' 카테고리의 다른 글
06 연관관계 Mapping 종류 (2) | 2021.08.21 |
---|---|
05 연관관계 (0) | 2021.07.28 |
04 Entity (3) | 2021.07.08 |
02. JPA 요소들 (2) | 2021.06.29 |
01. JPA 소개 (0) | 2021.05.19 |