JPA를 이해하는데 가장 중요한 용어이다.
굳이 번역하자면 "엔티티를 영구 저장하는 환경"이라는 뜻이다.
EntityManager.persist(entity);
"엔티티 매니저에서 persist를 호출해 entity를 집어넣음"
우리는 이렇게 객체를 저장하는구나 배웠었지만 .persist
는 사실 이걸 DB에 저장한다는 것이 아니라 영속성 컨텍스트라는 곳에 저장한다는 뜻이었다.
영속성 컨텍스트는 논리적인 개념이다.
눈에 보이지 않으며 엔티티 매니저를 통해 영속성 컨텍스트에 접근한다.
엔티티에는 생명주기가 존재한다.
비영속 (new/transient)
new상태라고 하며 영속성 컨텍스트와 전혀 관계가 없는 새로운 상태를 이른다.
영속 (managed)
영속성 컨텍스트에 관리되는 상태를 이른다.
준영속 (detached)
영속성 컨텍스트에 저장되었다가 분리된 상태를 이른다.
삭제 (removed)
삭제된 상태이다.
// 회원 엔티티를 영속성 컨텍스트에서 분리, 준영속 상태임
em.detach(member);
// 객체를 삭제한 상태
em.remove(member);
영속성 컨텍스트의 이점
- 1차 캐시
- 동일성(identity) 보장
- 트랜잭션을 지원하는 쓰기 지연(transactional write-behind)
- 변경 감지(Dirty Checking)
- 지연 로딩(Lazy Loading)
1차 캐시로 반복 가능한 읽기 (REPEATABLE READ) 등급의 트랜잭션 격리 수준을 데이터베이스가 아닌 애플리케이션 차원에서 제공
트랜잭션을 지원하는 쓰기 지연
커밋하는 순간 데이터베이스에 INSERT SQL을 보냄
Member memberA = em.find(Member.class, "memberA");
em.remove(memberA); // 엔티티 삭제
: 영속성 컨텍스트의 변경 내용을 데이터베이스에 반영하는 것
(커밋되면 자동으로 플러시가 발생)
영속성 컨텍스트를 플러시하는 방법
em.flush()
: 직접 호출트랜잭션 커밋
: 플러시 자동 호출JPQL 쿼리 실행
: 플러시 자동 호출📌 왜 JPQL 쿼리 실행시 플러시가 자동 호출될까?
em.setFlushMode(FlushModeType.COMMIT)
FlushModeType.AUTO
가급적 기본값 사용
커밋이나 쿼리를 실행할 때 플러시
FlushModeType.COMMIT
커밋할 때만 플러시
플러시는 영속성 컨텍스트를 비우지 않는다. 영속성 컨텍스트의 변경 내용을 데이터베이스에 동기화하는 것이 플러시이다.
트랜잭션이라는 작업 단위가 중요한 것이다. ➡️ 커밋 직전에만 동기화하면 됨.
우선 영속 상태가 되는 두 가지 루트는
1. em.persist()
2. DB에서 가져와 1차 캐시에 저장
➡️ JPA가 관리하는 상태
영속 상태 → 준영속 상태가 된 것을 말한다.
영속 상태의 엔티티가 영속성 컨텍스트에서 분리(detached). 한마디로 다 빼버리는 것이다.
준영속 상태가 되면 영속성 컨텍스트가 제공하는 기능을 사용하지 못한다.
em.detach(entity)
특정 엔티티만 준영속 상태로 전환
em.clear()
영속성 컨텍스트를 완전히 초기화
em.close()
영속성 컨텍스트를 종료
강의를 다 듣고나니 이해가 되는 그림😎