[JPA] 영속성 컨텍스트

Woong·2022년 6월 16일
0

Java

목록 보기
11/21

영속성 컨텍스트의 이점

  • 1차 캐시
  • 동일성(identity) 보장
  • 트랜잭션을 지원하는 쓰기 지연 (transactional write-behind)
  • 변경 감지(Dirty Checking)
  • 지연 로딩(Lazy Loading)

1차 캐시

  • 영속성 컨텍스트의 1차 캐시
  • 조회시 1차 캐시에서 조회를 함
    • 1차 캐시 조회 후 없으면 DB 조회
  • DB 조회 후 "1차 캐시에 저장 후" 반환
  • 다만, EntityManager 를 트랜잭션 단위로 만들고 종료시키므로, 요청 1개에 대해 사용되고 없어짐.
    • EntityManager 와 함께 없어지므로 큰 영향은 없음
  • 영속성 컨텍스트의 1차 캐시에 있는 객체를 다시 find 하면, 1차캐시 객체 그대로 돌려줌 (쿼리 발생 X)

동일성 보장

  • 영속 엔티티의 동일성 보장
  • find 한 객체의 == 비교를 해도 true 가 됨
  • DB가 아닌 애플리케이션 차원에서 제공
    • ※ 한 transaction 내에서.

트랜잭션을 지원하는 쓰기 지연

em.persist(memberA);
em.persist(memberB); // 이땐 INSERT SQL 발생 X
transaction.commt(); // 이때 INSERT SQL 을 보냄
  • persist 호출시, 쓰기 지연 SQL 저장소에 INSERT 쿼리를 저장

    • transaction.commit() 호출시, 쓰기 지연 SQL 저장소에 쌓인 SQL 이 flush 되고 commit됨
  • JPA 는 reflection 이 일어나기 때문에, default 생성자가 꼭 필요함

변경 감지

  • 엔티티 수정 변경 감지 (dirty check)
    • 객체 변경 시 자동으로 감지하여 UPDATE 됨
    • ※ persist 할 필요가 없음!!!
  • JPA commit 호출하면
  • flush 가 호출되고, 1차 캐시 내의 entity 와 스냅샷을 비교함
    • 스냅샷 : 최초에 영속성 컨텍스트에 들어왔을 때 객체 정보
    • 비교해서 데이터가 변경되었다?
      • -> UPDATE SQL 생성
      • -> 쓰기 지연 SQL 저장소에 저장
    • 쓰기 지연 SQL 장소 flush, commit 하여 DB에 반영

flush

  • flush
  • 영속성 컨텍스트의 변경 내용을 DB에 반영

변경 감지 (dirty check)

  • 수정된 엔티티에 대해 쓰기 지연 SQL 저장소에 등록
  • 쓰기 지연 SQL 저장소의 쿼리를 DB에 전송

영속성 컨텍스트를 플러시 하는 방법

  • em.flush() 직접 호출
  • 트랜잭션 커밋
  • JPQL 쿼리 호출

flush 해도 1차 캐시 유지됨

  • 쓰기지연저장소에 쌓인 SQL이 DB에 반영되는 과정

JPQL 쿼리 실행시 flush 가 자동 호출되는 이유

  • persist 만 하면 DB에 저장이 안되어있는데, 그 상태에서 JPQL 로 조회한다
    • -> flush 안하면 DB에 저장 안되어있으면 조회가 안되니까 문제가 됨
    • 그러므로 flush 한다.

flush 옵션

  • FlushModeType.AUTO
    • 커밋이나 쿼리를 실행할 때 플러시 (기본값)
  • FlushModeType.COMMIT
    • 커밋할 때만 플러시 (쿼리를 실행할 때에는 커밋을 하지 않는 옵션)

flush는 영속성 컨텍스트를 비우는 것이 아니다

  • 변경 내용을 DB에 동기화하는 것.
  • 트랜잭션이라는 작업 단위가 중요하므로, 커밋 직전에만 동기화하면 됨

준영속 상태

준영속 상태 (detached)

  • 영속 상태의 엔티티가 "영속성 컨텍스트에서 분리"

    • 객체 persist 하거나, DB에서 find 해오면 영속 상태. JPA가 관리중
  • ※ 준영속시 영속성 컨텍스트의 기능 사용 불가

    • -> 객체 변경이 일어나도 DB에 반영되지 않음 (dirty check X)

    준영속 상태가 되는 경우

em.detach(member); //특정 객체만
em.clear(); //영속성 컨텍스트 초기화 -> 1차 캐시 통으로 날림 -> 다 준영속 됨
em.close(); //영속성 컨텍스트 자체가 종료

reference

0개의 댓글