김영한 강사님의 '자바 ORM 표준 JPA 프로그래밍-기본편' 강의 정리
2022.03.17~ 03.31 진행
강의를 듣고 개인적으로 정리한 글입니다. 코드와 그림 출처는 김영한 강사님께 있습니다. 문제 있을 시 알려주세요.
영속성 컨텍스트
JPA는 영속성 컨텍스트에 엔티티를 저장한다. 영속성 컨텍스트는 "엔티티를 영구 저장하는 환경" 이라는 뜻이다. 영속성 컨텍스트는 논리적인 개념이며 눈에 보이지 않는다.
영속성 컨텍스트 접근하기
- 엔티티 매니저를 통해서 영속성 컨텍스트에 접근한다.
EntityManager.persist(entity);
를 하면 엔티티를 영속화한다. (DB에 저장하는게 아님, 영속성 컨텍스트에 저장)
엔티티 매니저 팩토리와 엔티티 매니저
EntityManagerFactory
를 통해서 고객의 요청이 올때마다 EntityManager
를 생성한다.
EntityManager
는 내부적으로 DB 커넥션을 통해 DB를 사용한다.
EntityManager를 생성하면 1대1로 영속성 컨텍스트가 생성되며 이렇게 1:1인 관계를 J2SE 환경이라고 한다.
J2EE, 스프링 프레임워크 같은 컨테이너 환경: 엔티티 매니저와 영속성 컨텍스트가 N:1
엔티티의 생명주기
- 비영속 (new/transient) : 객체만 생성한 상태로, 영속성 컨텍스트와 전혀 관계가 없는 새로운 상태
- 영속 (managed) : 영속성 컨텍스트에 관리되는 상태
EntityManager.persist(객체);
객체를 저장한 상태.
- 준영속 (detached) : 영속성 컨텍스트에 저장되었다가 분리된 상태
EntityManager.detach(객체);
- 삭제 (removed) : 삭제된 상태
EntityManager.remove(객체);
객체를 삭제한 상태 → 커밋되면 DB에서 삭제됨
엔티티 조회 - 1차 캐시
애플리케이션에서 엔티티를 조회할 때, 다음 과정을 거친다.
- 1차 캐시에 있는지 확인
- 1차 캐시에 없으면 DB를 조회해서 가져온다
- 1차 캐시에 저장한 후
- 객체를 반환
※ 1차 캐시의 유지 기간 : 고객의 요청(트랜잭션 단위)이 시작하고 끝날 때
=> 1차 캐시는 트랜잭션 단위로 유지되므로 성능 상 이점이 크지는 않지만, 영속 엔티티의 동일성을 보장해준다.
1차 캐시로 반복 가능한 읽기(REPEATABLE READ) 등급의 트랜잭션 격리 수준을 데이터베이스가 아닌 애플리케이션 차원에서 제공.
엔티티 등록 - 트랜잭션을 지원하는 쓰기 지연
EntityManger.persist(객체);
를 하면 객체들이 영속성 컨텍스트에 저장된다(=1차 캐시에 저장된다)transaction.commit();
이 실행되는 시점에 쓰기 지연 SQL 저장소에서 쌓인 쿼리들이 DB에 flush 되면서 최종 commit 된다.
=> 최적화 가능 : hibernate.jdbc.batch.size 옵션으로 DB에 한번에 여러 쿼리를 모아서 보낼 수 있는 등, 성능이 좋아 질 수 있다.
EntityManager em = emf.createEntityManager();
EntityTransaction transaction = em.getTransaction();
//데이터 변경시 트랜잭션을 시작해야함
transaction.begin(); // [트랜잭션] 시작
em.persist(memberA);
em.persist(memberB);
transaction.commit(); // [트랜잭션] 커밋 --SQL--> DB
엔티티 수정 - 변경 감지(Dirty Checking)
JPA는 변경 감지(Dirty Checking) 기능을 제공한다. App에서 엔티티를 수정하기만 해도 변경이 감지되어 DB에 반영을 해준다. 따라서 우리는 할 일이 없다!
- flush()
- 1차캐시와 스냅샷(최초로 영속성 컨텍스트에 저장된 시점)을 비교
- 변경사항이 있으면 SQL 저장소에 update 쿼리를 생성
EntityTransaction.commit()
→ flush → DB commit
Flush
flush는 영속성 컨텍스트의 변경내용을 데이터베이스에 반영하는 작업이다.
flush를 하면 다음 과정을 거친다.
- 변경 감지
- 수정된 엔티티를 쓰기 지연 SQL 저장소에 등록
- 쓰기 지연 SQL 저장소의 쿼리를 데이터베이스에 전송(등록, 수정, 삭제 쿼리)
- 즉 영속성 컨텍스트의 변경내용을 데이터베이스에 동기화한다.
※ 주의 : flush가 영속성 컨텍스트를 비우지는 않음. DB에 내보낼 뿐
트랜잭션이라는 작업 단위가 중요 → 커밋 직전에만 동기화하면 된다(??)
영속성 컨텍스트를 flush하기
- em.flush() - 직접 호출
- 트랜잭션 커밋을 하거나, JPQL 쿼리 실행을 하면 자동 플러시된다.
JPQL 쿼리 실행시 플러시가 자동으로 호출되는 이유?
JPQL에서 사용할 객체가 실제 DB에 저장되어 있지 않으면 곤란한 상황들이 있을 수 있기 때문
준영속 상태
영속 상태의 엔티티가 영속성 컨텍스트에서 분리(detached)된 상태를 준영속 상태라고 한다.
준영속 상태에서는 영속성 컨텍스트가 제공하는 기능을 사용하지 못한다.
준영속 상태로 만들기
em.detach(entity)
: 특정 엔티티를 준영속 상태로 전환em.clear()
: 영속성 컨텍스트 초기화em.close()
: 영속성 컨텍스트 종료
영속성 컨텍스트의 이점 정리
- 1차 캐시
- 동일성(identity) 보장
- 트랜잭션을 지원하는 쓰기 지연 (transactional write-behind)
- 변경 감지(Dirty Checking)
- 지연 로딩(Lazy Loading)
'Web > JPA' 카테고리의 다른 글
[Inflearn] JPA - 값 타입(작성전) (0) | 2022.05.11 |
---|---|
[Inflearn] JPA - 객체지향 쿼리 언어 (0) | 2022.03.31 |
[Inflearn] JPA - 엔티티매핑 (0) | 2022.03.22 |
[Inflearn] JPA 시작하기 + JPQL이란? (0) | 2022.03.21 |
[Inflearn] ORM, JPA란 무엇인가 (0) | 2022.03.21 |