JPA

1차캐시의 이점

winwin-k9 2023. 1. 2. 20:59

영속컨텍스트에는 1차 캐시가 있는데, key와 값(객체자체)으로 매핑이 된다.

만일 조회를 한다고 해보다.

조회를 하게되면 DB를 뒤지는게 아니라 1차캐시를 뒤지게된다.

따라서 캐시의 값을 조회한다.

 

DB에 있고, 캐시에는 없는 member2를 조회한다고 하면

먼저 1차캐시를 찾아본다.

이후 1차캐시에 member2가 없으므로 DB를 조회하는데, 조회 후 member2를  1차캐시에 저장하게 된다.

또한 이때 엔티티의 동일성을 보장하기 때문에 동일성 비교를 하면 true가 나오게 된다.

 

entityManager는 트랙젝션이 끝나면 그 안의 영속성 컨텍스트는 모두 지워지게 된다. 따라서 짧은 찰나의 순간에 이점이 있다.

Member member = new Member();
member.setId(10L);
member.setName("B");

em.persist(member);

Member findMember = em.find(Member.class, 10L);
tx.commit();


영속된 상태의 값 즉, 1차캐시에 값이 저장되어 있기 때문에 select쿼리가 나가지 않는다.

객체저장을 삭제하고 다시 실행시키면


컨텍스트와 캐시모두 초기화 되기 때문에 DB로부터 select쿼리로 가져와서 저장을 하게된다.

 

쓰기지연

em.persist(memberA)

여기까지 INSERT SQL을 데이터베이스에 보내지 않고, JPA가 이를 쌓고 있다.

이를 Commit()할때 데이터베이스에 INSERT SQL을 보낸다. 

persist를 하는순간 캐시에 저장되고, JPA가 이 Entity를 분석해서 INSERT쿼리를 생성한다.

그리고 쓰기지연 SQL저장소에 저장을 한다.

 

commit을 하는 시점에 쓰기지연 SQL저장소에 있던 것들이 flush되고, 실제 DB에 commit된다.

즉, 한번에 DB에 넣는 버퍼같은 역할을 한다.

 

변경 감지

Member member = em.find(Member.class, 10L);
member.setName("ZZ");
            

tx.commit();

이때 값을 변경하고 DB에 값을 다시 넣기 위해 em.persist를 해주어야 할까? 전혀 아니다.

JPA는 변경감지를 해준다.

데이터를 찾은 후 데이터를 변경만 하면 자동으로 update쿼리가 나가게 된다(마치 collection을 다루는 것처럼).

 

JPA는 DirtyChecking(변경감지)기능으로 엔티티 변경이 가능하다.

DB를 commit시점을 하는 순간에 내부에서 flush가 호출된다.

후에 entity와 스냅샷을 비교한다.

스냅샷은 값을 읽은 최초의 시점의 상태를 저장한다(최초로 영속성 컨텍스트, 1차 캐시에 들어온 상태).

이때 entity를 변경하면 commit하는 시점에 JPA가 entity와 스냅샷을 비교한다.
비교후 엔티티가 변경이 되었으면 Update쿼리를 쓰기지연 SQL에 저장한다.

그리고 이를 DB에 반영 하고commit하게 된다.

flush는 영속성 컨텍스트의 변경내욜을 DB에 반영하는 작업이다.
  • 변경감지
  • 수정된 엔티티 쓰기 지연 SQL 저장소에 등록
  • 쓰기 지연 SQL 저장소의 쿼리를 데이터베이스에 전송 (등록, 수정, 삭제 쿼리)

 

728x90