영속성 관리 - 내부 동작 방식

OneTwoThree·2023년 7월 23일
0

출처


영속성 컨텍스트

EntityManagerFactory를 통해 고객의 요청이 올 때 마다 EntityManager를 생성한다. EntityManager는 내부적으로 DB 커넥션을 활용해서 DB를 사용한다.

  • 엔티티를 영구 저장하는 환경
  • EntityManager.persist(entity)
    • 엔티티를 영속성 컨텍스트에 저장하는 것임
  • 영속성 컨텍스트는 논리적인 개념
  • 눈에 보이지 않는다
  • 엔티티 매니저를 통해 영속성 컨텍스트에 접근

엔티티의 생명주기

  • 비영속 : 영속성 컨텍스트와 관련 없는 새로운 상태
  • 영속 : 영속성 컨텍스트에 관리되는 상태
  • 준영속 : 영속성 컨텍스트에 저장되었다가 분리된 상태
  • 삭제 : 삭제된 상태
            //비영속
            Member member = new Member();
            member.setId(100L);
            member.setName("HelloJPA");

            //영속
            em.persist(member);

            //준영속
            em.detach(member);

            //삭제
            em.remove(member)

영속성 컨텍스트에는 id, Entity를 key, value로 갖는 1차 캐시가 있다. em.persist로 1차 캐시에 저장하고 em.find 하면 1차 캐시에서 먼저 조회한다. db에는 있고 1차 캐시에는 없는 데이터는 먼저 1차 캐시를 찾아보고 없으면 db에서 조회해서 1차 캐시에 저장하고 반환한다.
영속성 컨텍스트는 동일성을 보장한다(같은 키값으로 꺼내면 == 비교 시 true)

영속성 컨텍스트가 있어서 트랜잭션을 지원하는 쓰기 지연이 가능하다.
영속성 컨텍스트에는 쓰기 지연 SQL 저장소가 있어서 쿼리문이 쓰기 지연 SQL 저장소에 있다가 transaction.commit()하면 flush가 되면서 DB에 쿼리문이 날라가고 커밋한다.

            Member member1 = new Member(150L, "A");
            Member member2 = new Member(160L, "B");

            em.persist(member1);
            em.persist(member2);
            System.out.println("==================");

            tx.commit();

또한 엔티티 수정 시 변경 감지가 가능하다.


            Member member = em.find(Member.class, 150L);
            member.setName("ZZZZZ");


            tx.commit();

persist로 저장해주지 않고 setName으로 변경만 해도 알아서 UPDATE 쿼리가 나간다.
1차 캐시에 스냅샷이 있다. (영속성 컨텍스트로 최초로 읽어온 시점의 상태를 저장함)
JPA가 commit하는 시점에 내부적으로 flush()가 호출된다.
그 때 엔티티랑 스냅샷을 비교한다. 바뀐게 있으면 쓰기 지연 SQL 저장소에 UPDATE 쿼리를 만들어서 DB예 반영하고 커밋한다.

DELETE도 마찬가지로 커밋 시점에 쿼리가 나간다.

플러시

영속성 컨텍스트의 변경 내역을 DB에 반영하는 것

영속성 컨텍스트를 플러시 하는 방법은 3가지가 있다.

  • em.flush() 직접 호출

            Member member = new Member(200L,"member200");
            em.persist(member);

            em.flush();
            
            tx.commit();
  • 트랜잭션 커밋 : 플러시 자동 호출
  • JPQL 쿼리 실행 : 플러시 자동 호출
    • JPQL 쿼리 실행시 플러시가 자동 호출되는 이유

플러시는

  • 영속성 컨텍스트를 비우지 않음
  • 영속성 컨텍스트의 내용을 DB에 동기화
  • 트랜잭션 커밋 직전에만 동기화 하면 됨

준영속 상태

영속 상태의 엔티티가 영속성 컨텍스트에서 분리되는 것이다.
영속성 컨텍스트가 제공하는 기능을 사용하지 못한다.

준영속 상태로 만드는 방법

  • em.detatch(entity) : 특정 엔티티만 준영속 상태로 변환
  • em.clear() : em 안의 영속성 컨텍스트를 다 지움
  • em.close() : 영속성 컨텍스트를 닫아버림

0개의 댓글