JPA 영속성

매니·2022년 9월 20일
0

JPA

목록 보기
2/2
post-thumbnail

JPA 의 특징 중 하나인 영속성 컨텍스트에 관해서 알아볼까 합니다!

JPA 의 가장 중요한 것은 영속성 컨텍스트를 지원한다는 것 입니다.

여기서 저는 너무나도 헷갈렸죠 영속성?? 영속성 컨텍스트를 지원한다는게 대체 무슨말이지??

차근차근 제가 이해한바를 통해서 설명하도록 하겠습니다.

영속성 컨텍스트

영속성 컨텍스트를 한마디로 정의하자면, 엔티티를 영구 저장하는 환경 이라는 뜻이다.

엔티티의 생명주기

  • 비영속
    영속성 컨텍스트와 전혀 관계가 없는 새로운 상태

  • 영속
    영속성 컨텍스트에 관리되는 상태

  • 준영속
    영속성 컨텍스트에 저장되었다가 분리된 상태

  • 삭제
    삭제된 상태

영속

Member member = new Member();
member.setId("member1");
member.setName("유저1");

EntityManager em = emf.createEntityManager();
em.getTransaction().begin();

위의 상태는 비영속 상태이다.

em.persist(member);

이렇게 persist 를 호출하여 영속 상태로 만들어 줄 수있다.

위에 아무리 setId, setName 을 한들 영속성 컨텍스트에는 영향을 주지않는다.

그러나 em.persist(member); 을 해준 순간부터 해당하는 쿼리는 컨텍스트에 저장되고 이것이 마지막으로 commit()를 만났을때 DB에 데이터가 저장되거나 쿼리가 실행된다.

그렇기 때문에 트랜잭션 처리도 쉽게 가능하다.

왜냐하면 모든 쿼리는 em.persist 를 만났을때 전송되는 것이 아니라 commit()를 만나면 전송되고, commit()를 만나기 전에 어떠한 문제가 있다면 전부다 rollback 이 가능하기 때문이다.

여기서 트랜잭션에 대해서 간단히 짚고 넘어가자면,

트랜잭션

트랜잭션이란 데이터베이스 내에서 쪼갤 수 없는 업무 처리의 최소 단위를 일컫는다.

가장 많은 예시를 드는것이 은행업무라고 볼 수 있다.

A 가 B 에게 돈을 1000원 송금하였다.

이 상황에서 A의 계좌에서는 1000원 빠져야되고 B의 계좌에서는 1000원 추가가 되어야한다.

만약 A의 계좌에서는 1000원이 빠졌지만 B의 계좌에서는 1000원이 추가가되지 않았다.

그렇다면 정말 큰 일이 일어난 것이다. 돈이 공중분해 되어서 사라져버렸으니깐,

1번째, A의 계좌에서 1000원이 빠지는것 조차 오류라고 오류 메세지를 던져줘야한다.

두개다 실행되지 않을 것이라면 둘다 실행되서는 안된다.

그것이 더이상 쪼갤 수 없는 업무의 단위인것이다. 두가지 업무는 절대 뗄레야 뗄수없는 단위니깐, 그것이 트랜잭션이다.

영속성의 이점

다시, 이러한 영속성의 이점에는 아래와 같은 이점이 있다.

  • 1차 캐시
  • 동일성 보장
  • 트랜잭션을 지원하는 쓰기 지연
  • 변경 감지
  • 지연로딩

1차 캐시

1차 캐시라는 말은 엔티티를 추가할때, em.persist(member) 이런식으로 추가하게 된다.

그 뒤에 조회를 하게 된다면 JPA는 DB에서 조회하는 것이 아니라 영속된 캐시내에서 조회를 하게되고 DB까지 가서 조회하지 않아도 되는 이점을 갖고 있다.

성능면에서 조금 도움을 줄 수 있다.

영속 엔티티의 동일성 보장

1차 캐시내에서 조회를 하기 때문에 만약 같은 member_Id = 100 을 2번 조회한다면 둘다 DB에서 조회하는 것이 아니라 첫번째는 DB에서 조회, 두번째는 1차 캐시 내에서 조회를 하게된다.

그렇게 때문에 두개는 동일하다는 것을 보장 받을 수 있다.

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

위에서 짧게 설명을 했던 부분이다.

영속 컨텍스트에 저장되게 되고 commit를 만나야 DB에 저장되거나 반영되기 때문에 트랜잭션 처리가 쉽게 가능하다.

변경감지

이것은 update 쿼리를 짤때 굉장히 효과를 보는데,

update 쿼리는 단순히 조회를 해주고 그 조회에서 setUserName setUserID 를 해주면 그냥 변경이 된다.

이것은 변경감지의 이점에서 나올 수 있는 것이다.

변경을 감지하게되면 update 쿼리문을 생성하게 되고 이것이 쓰기지연 SQL 저장소에 넘어가고 이것을 1차 캐시와 비교하게 된다.

그래서 1차 캐시와 다르다는 것을 감지하면 update 쿼리를 flush(쿼리문을 DB에 보낸다.) 해준다.

플러시

플러시란, 영속성 컨텍스트의 변경내용을 데이터베이스에 반영시켜주는 것이다.

보통 영속성 컨텍스트에 있는 내용은 commit 를 만나야 DB에 저장된다.

하지만, 강제적으로 DB에 저장시켜줄 수 있다.

em.flush()

위에있는 코드를 불러주기만 하면 flush 되며 DB에 쿼리가 보내진다.

플러시의 특징

  • 영속성 컨텍스트를 비우지 않는다.
  • 영속성 컨텍스트의 변경 내용을을 DB에 동기화시켜준다.
  • 트랜잭션이라는 작업 단위가 중요하며, 커밋 직전에만 동기화 해주면 된다.

준영속 상태 (디테치 상태)

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

준영속 상태로 만들기

  • em.detach(entity)
    특정 엔티티만 준영속 상태로 전황

  • em.clear()
    영속성 컨텍스트를 완전히 초기화

  • em.clear()
    영속성 컨텍스트를 종료

💡 I Learned

강의를 들으면서 영속성이 대체 무엇이고 어떤 것을 뜻하는거지? 대체 뭘까? 라는 의문점이 해결되었다.

영속성 컨텍스트는 쿼리문을 저장하는 단계이며, commit 를 만났을때 해당 쿼리들이 슈르륵 DB에 전송된다는 것을 알게되었다.

또한, update 쿼리문 같은 경우에는 변경을 감지해서 플러시 해준다는 것을 알게 되었다.
의도적으로 영속성 컨텍스트에 넣어주지 않아도 알아서 변경을 감지하고 영속성 컨텍스트에 쿼리문을 넣어준다고 이해하였다.

공부하면 할수록 재밌어지는 분야이고 좀 더 알아보고싶다.

profile
성장중 🔥

0개의 댓글