[JPA] 영속성 컨텍스트 (JPA 기본편 by 김영한)

su_y2on·2022년 1월 19일
0

JPA

목록 보기
2/17
post-thumbnail

영속성 컨텍스트

영속성 컨텍스트✨ 는 엔티티를 영구적으로 저장하는 환경이며 논리적인 개념입니다. 접근은 Entitymanager를 통해가능하며 DB로 가기전에 있는 가상공간이라고 생각하며 됩니다.



엔티티의 생명주기

엔티티의 생명주기는 그림으로 나타내면 아래와 같습니다.

하나씩 먼저 살펴보면 먼저 member객체를 생성한 것은 비영속 상태입니다. 즉 영속성 컨텍스트와 관련없는 상태입니다. 그후에 EntityManager를 통해 persist로 영속상태로 만들어줍니다. 이때 member은 영속성 컨텍스트 안으로 들어갑니다.

후에 detach통해 영속성 컨텍스트에서 분리될 수 있습니다.

이외에도 clear영속성 컨텍스트를 아예 비우는 것이기 때문에 들어있던 모든 엔티티들이 분리됩니다.

close는 EntityManager를 닫는 것으로 영속성 컨텍스트는 사라집니다.


//          > 비영속
            Member member = new Member();
            member.setId(2L);
            member.setName("HelloB");
//          > 영속
            em.persist(member);
//          > 영속해지
            em.detach(member);

remove는 회원삭제를 할 때 사용했는데요 이때는 commit시에 flush되면서 변경사항(삭제)가 DB에 반영됩니다.




영속성 컨텍스트의 이점

아무래도 중간에 있는 공간이기 때문에 여러 이점들을 제공합니다

1차 캐시

persist로 영속상태가 되면 key(pk): value(entity) 형태로 캐시에 저장이 됩니다. 따라서 같은 transaction안에서는 캐시가 유지됩니다. 후에 find를 할 경우 먼저 1차 캐시에서 있는지 살펴본 뒤에 없다면 select 쿼리를 날려서 찾아오기 때문에 쿼리 날리는 횟수를 조금은 줄일 수 있습니다. (하지만 한 transaction안에서만 적용되어서 큰 성능개선은 없습니다)

1차 캐시에 없다면 DB에서 조회해오고 이를 바로 또 1차 캐시에 저장합니다.




영속성 엔티디 동일성 보장

영속성 엔티티가 있어 아래와 같은 일이 가능합니다

Member a = em.find(Member.class, "member1");
Member b = em.find(Member.class, "member1");
System.out.println(a == b);

사실 이거 너무 당연한거 아니야? 라고 생각하실 수 있지만 데이터베이스 차원에서 위와 같이 sql을 날려서 비교하면 a와 b가 다릅니다. 물론 id값은 같습니다. 영속성 컨텍스트가 있어 객체간 비교를 편하게 할 수 있습니다.




쓰기지연

영속성 컨텍스트는 DB전에 있는 단계로 buffer와 같은 역할을 합니다. 따라서 변경사항을 모아놨다가 commit()시에 flush가 되면서 DB에 반영이(쿼리가 날라간다)됩니다.

//엔티티 매니저는 데이터 변경시 트랜잭션을 시작해야 한다.
transaction.begin(); // [트랜잭션] 시작

em.persist(memberA);
em.persist(memberB);
//여기까지 INSERT SQL을 데이터베이스에 보내지 않는다.

//커밋하는 순간 데이터베이스에 INSERT SQL을 보낸다.
transaction.commit(); 




변경감지(dirty check)

이 기능으로 이전에 회원수정이 간단하게 객체의 속성을 바꾸는 것만으로 끝났던 것입니다. 영속성 컨텍스트는 commit으로 flush가 실행되면 변경사항들을 체크해 update를 해줍니다. 체크하는 방식은 영속성 컨텍스트에 들왔을 최초의 모습을 스냅샷으로 떠놓고 그뒤에 flush할 때 실제 entity와 스냅샷을 비교해서 달라진 것을 감지합니다.

0개의 댓글