영속성 컨텍스트 (Persistence Context) 정의

 

영속성 컨텍스트란 엔티티를 영구 저장하는 환경. 어플리케이션이 데이터베이스에서 꺼내온 데이터 객체를 보관하는 역할을 하는 환경을 의미한다.

 

  • 엔티티 매니저 

영속성 컨텍스트를 관리하는 관리자.

특정 작업을 위해 데이터베이스에 접근하고 엔티티를 CRUD하는 역할 및 엔티티 관련 일을 처리하는 관리자이다.  엔티티 매니저를 통해 엔티티를 조회하거나 저장할 때 엔티티를 보관하고 관리한다. 엔티티 매니저마다 따로 공간을 가진다.

 

  • 엔티티 매니저 팩토리 

스레드가 하나 생성 될 때 마다 엔티티 매니저를 생성한다.

엔티티 매니저에 여러 스레드가 동시 접근하여 동시성 문제가 발생하기 때문에 엔티티 매니저를 공유하면 안되는데 엔티티 매니저 팩토리가 통해서는 여러 스레드가 동시 접근할 수 있게 해준다.

다만, 엔티티 매니저 팩토리는 설정 정보를 읽어와 DB 커넥션 풀도 생성하기 때문에 생성하는 데 굉장히 큰 비용이 든다. 따라서 어플리케이션 전체에 하나만을 생성하여 공유해 사용해야 한다.

 

 

 

출처 자바 ORM 표준 JPA - https://product.kyobobook.co.kr/detail/S000000935744

 

 


영속화 한다

엔티티 매니저가 자기의 영속성 컨텍스트에 넣어 관리한다는 의미

 

 


JPA의 엔티티 생명주기 상태

  • 비영속(New (새로운) / Transient (일시적인)) 

영속성 컨텍스트와 관계가 없는 새로운 상태로 이 상태 객체의 데이터 생성 및 변경은 DB와 관련없고 그저 Java 객체로써 존재.

// 엔티티를 생성
Member member1 = new Member();
member.setId("id123");
member.setName("이순신");

 

  • 영속(Managed) 

엔티티 매니저를 통해 엔티티가 영속성 컨텍스트에 저장되어 관리되는 상태. 이 상태 객체의 데이터가 생성되거나 변화되면 JPA가 이를 추적하면서 필요에 따라 DB에 반영한다.

entityManager.persist(member1);

 

  • 준영속(Detached) 

관리되다가 영속성 컨텍스트에서 분리된 상태

// 엔티티를 영속성 컨택스트에서 분리
entityManager.detach(member1);
// 영속성 컨텍스트를 비우기
entityManager.clear();
// 영속성 컨택스트를 종료
entityManager.close();

 

  • 삭제(Removed) 

영속성 컨텍스트에서 삭제된 상태

entityManager.remove(member1);

 

 


영속성 컨텍스트의 이점

 

  • 1차 캐시 

DB를 이용하는 작업은 부하가 심한 작업이기 때문에 자주하는 것을 줄여야 할 필요가 있다.

그래서 매번 DB의 데이터를 얻기위해 DB와 직접 쿼리를 날려 작업하는 걸 줄이기 위해 DB에서 가져온 데이터를 임시로 저장하는 "1차 캐시"를 영속성 컨텍스트 내부에 두게 된다.

JPA에서 1차 캐시를 이용하는 과정은 아래와 같다

 

    1. find("이순신")와 같은 로직이 있을 때 먼저 1차 캐시를 조회

    2-1. 1차 캐시 안에서 있으면 해당 데이터 반환

    2-2. 1차 캐시에 없으면 실제 DB로 해당 쿼리를 보낸다

    3. 해당 결과를 반환하기 전 1차캐시에 저장하고 반환

 

단, 1차 캐시는 해당 Transaction과 생명주기가 같다는 단점이 있다. 

 

  • 쓰기 지연 SQL 저장소 

트랜잭션을 지원하는 쓰기 지연(Transactional Write-behind)의 가장 큰 장점은 데이터베이스 테이블 로우에 락이 걸리는 시간을 최소한다.

쓰기 지연을 사용하지 않고 그때 그때 SQL을 직접 다루면 UPDATE SQL을 실행할 때 마다 테이블 로우에 락이 걸린다.

하지만 쓰기 지연을 사용하면 트랙잭션이 커밋되기 전까지의 SQL을 쌓아두고 있어 트랜잭션 진행 중에 데이터 베이스 로우에 락을 걸지 않고 커밋된 순간에만 해당 로우에 락을 걸어 시간을 최소화 한다. 따라서 동시에 더 많은 트랙잭션을 처리 할 수 있게 한다.

 

    1. 엔티티를 영속화할때 엔티티를 1차 캐시에 저장

    2. 쓰기 지연 SQL 저장소에 insert SQL을 저장하여 쌓아둔다

    2. entityManager.commit() 메소드 호출 

    3. 내부적으로 지연 SQL 정장소에서 Flush (변경 내용을 데이터 베이스에 동기화) 가 일어난다

    4. "Insert A", "Insert B"와 같은 쓰기 전용 쿼리들이 DB로 흘러가 반영된다. 

 

  • DirtyChecking(변경 감지) 

데이터의 변경을 감지해 자동으로 수정한다.

1차 캐시에는 DB의 엔티티의 정보만 저장하는 것이 아니라 해당 엔티티를 조회한 시점의 데이터 정보를 같이 저장해둔다. 

엔티티객체와 조회 시점의 데이터가 달라졌다면 변경이 발생했다는 걸 인지하고 해당 변경 부분에 대한 Update 쿼리를 작성해 쓰기 지연 SQL 저상소에 넣어둔다. 

 

    1. 트랜잭션을 commit하면 엔티티 매니저 내부에서 먼저 flush 호출

    2. 엔티티와 *스냅샷을 비교해서 변경된 엔티티를 검색

    3. 변경된 엔티티가 있으면 변경 부분에 대한 Update 쿼리를 생성해서 쓰기 지연 SQL 저장소에 저장

    4. commit()이나 flush()가 일어나면 쓰기 지연 저장소의 SQL을 데이터베이스에 전송

    5. 데이터베이스 트랜잭션을 commit 하여 반영

 

+ 엔티티를 영속성 컨텍스트에 보관할 때, DB의 엔티티에 조회하여 가져온 최초 상태를 복사해 저장해 둔걸 스냅샷이라고 한다. 그리고 플러시 시점에서 스냅샷과 엔티티를 비교해 변경된 엔티티를 찾는다.

+ 주특기입문 과제때 업데이트를 하면서 save와 같은 메서드를 호출하지 않았는데도 변경되었던 걸 생각하면 된다. 

 

  • 데이터의 어플리케이션 단의 동일성 보장 
Member member1 = em.find(Member.class, "minsook");
Member member2 = em.find(Member.class, "minsook");
System.out.println(member1 == member2) => true

 

위의 Member1와 Member2를 == 비교를 하게되면 같다는 결과가 나온다.

JPA는 영속 엔티티의 동일성을 보장해주는데 java 컬렉션에서 값을 가져 올때 동일한 주소 값을 가져오듯이, 같은 reference를 불러오면 같은 1차 캐시 안에서 값을 가져와 동일성을 보장하는 것이다. 

 

 

 

 


참조 링크들: 

 

3.영속성 관리 · jpa

 

ultrakain.gitbooks.io

 

1. 엔티티 (Entity) 와 엔티티 매니저 (Entity Manager)

엔티티 매니저 특정 작업을 위해 데이터베이스에 액세스하는 역할을 담당한다. 엔티티를 DB 에 등록/수정/삭제/조회(CRUD) 하는 역할이며, 엔티티와 관련된 일을 처리하는 엔티티 관리자이다. - 엔

lhwn.tistory.com

 

[JPA] 영속성 컨텍스트

JPA에서 가장 중요한 2가지 아래와 같다.객체와 관계형 데이터베이스 매핑영속성 컨텍스트JPA를 이해하는데 가장 중요한 용어엔티티를 영구 저장하는 환경 이라는 뜻EntityManager.persist(entity);데이

velog.io

 

JPA 플러시 정리 - Yun Blog | 기술 블로그

JPA 플러시 정리 - Yun Blog | 기술 블로그

cheese10yun.github.io

 

+ Recent posts