JPA. 엔티티와 영속성 컨텍스트?

무지성개발자·2024년 1월 31일
0

JPA

목록 보기
2/12

엔티티 매니저

JPA는 엔티티 매니저를 사용해서 CRUD를 한다. 엔티티 매니저는 엔티티 매니저 팩토리를 통해 얻을 수 있으며, 스레드간의 공유를 하면 안된다.

엔티티 매니저를 통해 CRUD를 할 때 DB에 바로 접근한다고 보이지만 사실 영속성 컨텍스트에 먼저 작업한다고 보면된다.

  • 삽입 : 영속성 컨텍스트에 데이터를 올림.
    • insert 쿼리는 쓰기저장소에 저장되어 있다가 추후 DB에 저장.
  • 수정 : 영속성 컨텍스트에 데이터를 변경.
    • 원본 데이터랑 비교 후 추후 DB에 변경.
  • 삭제 : 영속성 컨텐스트에 데이터를 삭제.
    • delete 쿼리는 쓰기저장소에 저장되어 있다가 추후 DB에 삭제.
  • 조회 : 먼저 영속성 컨텍스트에 데이터가 있는지 조회 후 없다면 DB에서 조회 후 영속성 컨텍스트에 저장하고 반환.
    • 영송석 컨텍스트에 데이터가 있다면 DB접근 안함.

영속성 컨텍스트

영속성 컨텍스트는 논리적인 개념으로 보이는 것은 아니고, 엔티티 매니저를 통해 접근이 가능하다. 영속성 컨텍스트는 쓰기 지연 SQL 저장소, 1차 캐시이 포함되어 있다.

엔티티 생명주기

영속성 컨텍스트에 저장된 객체는 영속성 컨텍스트의 관리를 받는다고 하며, 생명주기를 갖는다.

비영속

비영속 상태는 new 키워를 통해 생성한 객체를 영속성 컨텍스트에 올리지 않은 상태를 말하며, 아직 한번도 저장하지 않은 상태다. persist()를 통해 영속성 컨텍스트에 올릴 수 있다.

영속

영속 상태는 영속성 컨텍스트에 저장되어 있는 상태를 말하며 영속성 컨텍스트의 관리를 받는다. 비영속 상태를 persist() 또는 조회한 데이터가 영속성 컨텍스트에 저장된 상태다.

준영속

준영속 상태는 영속성 컨텍스트에 저장 되었다가 분리된 상태를 말하며 영속성 컨텍스트의 관리를 받지 않는 상태를 말한다. 준영속 상태는 detach(entity), clear(), close()로 만들 수 있으며 merge()를 통해 다시 영속 상태를 만들 수 있다.

  • detach(entity) : 영속성 컨텍스트에서 entity 하나를 분리.
  • clear() : 영속성 컨텍스트 비움(모든 entity가 분리됨).
  • close() : 영속성 컨텍스트를 닫음.

삭제

삭제 상태는 영속성 컨텍스트에서 삭제가 된 상태로 영속성 컨텍스트의 관리를 받지 않는다. remove()로 삭제 상태로 만들며, persist()로 다시 영속상태로 관리 할 수 있다.

준영속과 삭제는 둘다 영속성 컨텍스트에서 분리 되서 관리를 받지 못 하는 상태지만 준영속은 db에 삭제하는 아니며, 삭제는 db에도 삭제하는 상태라는 차이가 있다.

영속성 컨텍스트 관리

영속성 컨텍스트의 관리를 받는다는건 1차캐시, 쓰기 지연 같이 영속성 컨텍스트의 기능을 사용할 수 있다는 걸 의미한다.

쓰기지연

영속성 컨텍스트의 관리를 받는 객체들은 쓰기지연 기능을 사용할 수 있다. em.persist(entity)로 영속성 컨텍스트에 저장하면 바로 DB에 저장하는 것이 아니라 쓰기 지연 SQL저장소에 Insert문을 저장하고 추후에 db에 한번에 반영한다.

변경감지

변경감지는 영속성 컨텍스트의 관리를 받는 객체의 상태값을 변경했을 경우, 쓰기 지연 SQL저장소에 Update문을 저장 후 추후에 db에 반영하는 것이다.

영속성 컨텍스트가 변경감지를 하는 방법은 1차 캐시의 현재 entity와 영속성 컨텍스트에 저장 될 때의 entity의 스냅샷을 비교하여 다를 경우 update를 한다.

조회

영속성 컨텍스트에 저장된 데이터를 또 DB에서 조회하려고 한다면 DB에 접근하지 않고 영속성 컨텍스트에 저장된 데이터를 반환한다. 이때 데이터는 동일성을 보장 받는다.

삭제

삭제 역시 영속성 컨텍스트의 쓰기 지연 SQL 저장소에 delete 쿼리를 담아 뒀다가 추후 반영된다.

쓰기 지연 SQL 저장소

영속성 컨텍스트는 쓰기 지연 SQL 저장소에 SQL 쿼리를 담아 추후 반영한다. 여기서 추후 반영이란 여러시점이 있는데 트랜잭션의 커밋, flush, JPQL을 사용하는 시점이다.

트랜잭션 커밋

엔티티 매니저는 트랜잭션 단위로 할당 받아 사용하여 트랜잭션이 끝나면서 커밋할 때 모든 SQL을 DB에 전달한다. 트랜잭션 커밋할 때 내부적으로 flush가 동작한다.

JPQL사용

JPQL은 JPA에서 사용하는 SQL문이라고 생각하면 된다. JPQL은 바로 DB에서 데이터를 질의하기 때문에 쓰기 지연 SQL저장소에 반영되지 않은 데이터가 있다면 데이터의 정합성이 깨질 수 있기 때문에 먼저 flush를 동작시켜 변경 데이터를 저장하고 JPQL를 실행한다.

flush()

flush()는 쓰기 지연 SQL저장소의 쿼리들을 DB에 반영시킨다. 직접 사용할 수도 있다. 트랜잭션 커밋, JPQL을 사용해도 결국 flush()가 동작하여 데이터를 DB에 반영하니, flush()로 데이터를 반영한다고 생각해도 된다.

profile
no-intelli 개발자 입니다. 그래도 intellij는 씁니다.

0개의 댓글