JPA에서 가장 중요한 2가지
- 객체와 관계형 데이터베이스 매핑하기
- 영속성 컨텍스트
엔티티 매니저 팩토리와 엔티티 매니저
영속성 컨텍스트 (Persistence Context)
의미
- 엔티티를 영구 저장하는 환경
- 논리적인 개념이며, 눈에 보이지 않음
- 엔티티 매니저를 통해서 영속성 컨텍스트에 접근
엔티티의 생명주기
비영속 (new/transient)
영속성 컨텍스트와 전혀 관계가 없는 새로운 상태 (객체를 생성만 한 단계)
영속 (managed)
영속성 컨텍스트에 관리되는 상태 (persist)
준영속 (detached)
영속성 컨텍스트에 저장되었다가 분리된 상태
삭제 (removed)
삭제된 상태
장점
1차 캐시
- 엔티티를 조회할 때 영속성 컨텍스트에서 먼저 찾는다.
- 1차 캐시에 없다면 DB에서 조회한다.
- DB에서 조회한 객체를 1차 캐시에 저장한다.
하지만, 엔티티 매니저는 요청이 끝났을 때 없어지기 때문에 캐시도 같이 없어진다.
따라서 1차 캐시는 비즈니스 로직이 엄청 복잡하지 않는 이상, 성능의 이점을 얻을 수 있는 장점은 없다.
성능의 이점보다는 컨셉이 주는 이점 (객체지향적 코드 작성)
// 처음 조회, 1차 캐시 저장
Member findMember1 = em.find(Member.class, 1L);
// 두 번째 조회, 캐시에 존재하기 때문에 쿼리문X
Member findMember2 = em.find(Member.class, 1L);
동일성(identity) 보장
위의 두 객체의 동일성 비교 결과는 true
트랜잭션을 지원하는 쓰기 지연
- 쿼리 생성 후 쓰기 지연 SQL저장소에 쿼리문 저장
- 트랜잭션이 커밋되는 순간 SQL 저장소의 모든 쿼리문이 flush된 후 commit
변경 감지 (dirty checking)
자바 컬렉션에서 객체를 변경하고 다시 저장하지 않는 것과 같다.
- 트랜잭션 커밋
- 엔티티와 스냅샷 비교 후 다르면 UPDATE 쿼리를 SQL 저장소에 저장
- flush 및 commit
플러시 (Flush)
의미
영속성 컨텍스트의 변경내용을 DB에 반영하는 것
플러시 발생
- 변경 감지
- 수정된 엔티티 쓰기 지연 SQL 저장소 등록
- SQL 저장소의 쿼리(등록, 수정, 삭제 등)를 DB에 전송
영속성 컨텍스트를 플러시하는 방법
- 직접(강제) 호출 : em.flush()
- 자동 호출 : 트랜잭션 커밋, JPQL 쿼리 실행
플러시 모드 옵션
- 커밋이나 쿼리를 실행할 때 플러시(기본값) :
em.setFlushMode(FlushModeType.AUTO)
- 커밋할 때만 플러시(권장X) :
em.setFlushMode(FlushModeType.COMMIT)
요약
- 영속성 컨텍스트를 비우지 않음
- 영속성 컨텍스트의 변경내용을 DB에 동기화
- 플러시라는 매커니즘이 동작할 수 있는 이유는 트랜잭션이라는 작업 단위가 존재하기 때문이다.
준영속 상태
의미
- 영속 상태의 엔티티가 영속성 컨텍스트에서 분리됨(detached)
- 영속성 컨텍스트가 제공하는 기능을 사용하지 못함
ex) 변경 감지가 안 돼서 아무런 변화가 없음