[JPA] 영속성 관리

2022. 12. 19. 19:50DataBase/JPA

[JPA] 영속성 관리

 

  1. 엔티티 매니저 펙토리 & 엔티티 매니저
  2. 영속성 컨텍스트
  3. 엔티티의 생명주기
  4. 영속성 컨텍스트의 특징
  5. 플러시
  6. 준영속
  7. 정리

 

엔티티 매니저 펙토리 & 엔티티 매니저

 

엔티티 매니저 (EntityManager)

Make an instance managed and persistent.
Params:entity – entity instance
  • 엔티티 ( Entity )에 관한 모든 일 처리
    • 저장 / 수정 / 삭제 / 조회... etc
    • 엔티티를 저장하는 가상의 데이터 베이스

 

엔티티 매니저 팩토리 (EntityManager Factory)

Create a new application-managed EntityManager. This method returns a new EntityManager instance each time it is invoked. The isOpen method will return true on the returned instance.
Returns:entity manager instance
EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("example");

example이라는 unitname을 가진 EntityManager factory를 생성, 이때 괄호 안에 있는 example이란 이름을 가진 부분은 application.properties 부분에 선언하여 사용할 수 있다. 기존에는 persistence.mxl부분에 선언을 하여 해당 factory의 정보를 작성하였지만 application.properties를 사용하면 간단하게 선언이 가능하다.

#persistence.xml
<persistence-unit name="example">
 <properties>
   <!-- 드라이버, 연결정보 및 dialect 설정>
 </properties>
</persistence-unit>


# application.properties
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/jpa?serverTimezone=UTC&characterEncoding=UTF-8
spring.datasource.username=root
spring.datasource.password=1234

 

해당 factory에서 entity manager를 생성할 수 있다. 해당 경우로 entity manager를 생성하면 비용이 거의 들지 않는다

 

EntityManager entityManager = entityManagerFactory.createEntityManager();

//createEntityManager 
Create a new application-managed EntityManager with the specified Map of properties. This method returns a new EntityManager instance each time it is invoked. The isOpen method will return true on the returned instance.
Params:map – properties for entity manager
Returns:entity manager instance

 

웹 어플리케이션의 동작 - DB

 

  1.  요청이 들어옴
  2. factory에서 entity manager를 생성
  3. 만약 트랜잭션이라는 변경하는 최소한의 논리적 단위가 요청으로 들어오면 manager는 커넥션을 획득
  4. 획득한 커넥션으로 DB에 접근

 

영속성 컨텍스트

 

엔티티를 영구적으로 저장하는 환경 - 논리적 공간

 

매니저로 엔티티를 저장하거나 조회하면 매니저는 영속성 컨텍스트(저장 환경)에 엔티티를 보관하고 관리한다.

entityManager.persist(user);

해당 코드는 user라는 엔티티를 영속성 컨텍스트에 저장한다는 의미

 

 

엔티티 생명주기

 

 

entity 생명주기 - 4가지

 

  • 비영속 (new / transient)
    • 영속성 컨텍스트와 전혀 관계가 없는 상태 = DB에 관련이 없는 객체 상태
User user = new User();
user.setId(1);
user.setUsername("A");

 

  • 영속 (managed)
    • entity manager를 통해 엔티티가 영속성 컨텍스트에 저장되어 관리되고 있음
    • 데이터의 생성, 변경들을 JPA가 추적하면서 해당 내용을 DB에 반영
entityManager.persist(user);

 

  • 준영속 (detached)
    • 영속성 컨텍스트에 저장되었다가 분리가 된 상태
    • 이때 detach를 사용하여 준영속 상태로 변경 후에는 clear / close로 매니저를 닫아도 해당 엔티티는 준영속 상태
entityManager.detach(user);
entityManager.clear();
entityManager.clear();

 

  • 삭제 (removed) 
    • 영속성 컨텍스트 / 데이터베이스에서 삭제
entityManager.remove(user);

 

 

영속성 컨텍스트 특징

 

  • 영속성 컨텍스트와 식별자 값
    • 엔티티를 @Id(식별자 값)로 구분
    • 만약 해당 Id값이 없으면 예외 발생 
  • 영속성 컨텍스트와 DB 저장
    • JPA는 트랜잭션을 커밋하는 순간 영속성 컨텍스트에 저장된 엔티티를 DB에 반영 → 플러시
  • 영속성 컨텍스트의 엔티티 관리의 장점
    • 1차 캐시
    • 동일성 보장
    • 트랜잭션을 지원하는 쓰기 지연
    • 변경 감지
    • 지연 로딩

 


1차 캐시 -  영속성 컨텍스트 내부에 존재하는 캐시, 영속(managed()) 상태의 엔티티는 모두 이곳에 저장

 

1차 캐시와 DB

DB는 JPA를 통해 해당 DB를 사용하는 백엔드와 연결이 되어있다. 다만 이때 DB에서 데이터를 가져오는 것은 부하와 비용이 드는 작업이라고 한다. 그렇기에 이제 DB에 최소한으로 접근하기 위해 고안된 것이 바로 1차 캐시이다. 

 

위의 그림은 아래와 같다. 

만약 우리가 하나의 entity를 가져오고 싶다. 그런데 해당 entity가 자주 조회가 되어 DB에서 가져오게 되는 것이라 생각하자. 그렇다면 해당이 되는 entity를 1차 캐시에 저장을 해놓으면 DB까지 접근하는 것이 아닌 1차 캐시에서 접근을 하는 것으로 해당 entity를 가져올 수 있다. 

 

쓰기 지연 SQL 저장소

 

또한 1차 캐시에는 스냅샷이라는 부분이 존재한다. 이는 현재 entity와 작업 후의 엔티티를 비교하는 부분이다. 만약 변경내용이 감지가 되면 쓰기 지연 SQL 저장소에 DB에 적용될 수 있는 수정 쿼리를 넣어놓는다.

 

변경 감지 및 수정 과정 -  영속성 컨텍스트가 관리하는 영속 상태의 엔티티에만 적용

  1. 트랜잭션을 커밋하면 엔티티 매니저 내부에서 먼저 플러시 호출
  2. 엔티티와 스냅샷을 비교해서 변경된 엔티티를 찾는다
  3. 변경된 엔티티가 있으면 수정 쿼리를 생성해서 쓰기 지연 SQL 저장소에 입력
  4. 쓰기 지연 저장소의 SQL을 DB에 보냄
  5. DB의 트랜잭션을 커밋

 

 

플러시

 

영속성 컨텍스트 변경 내용이 데이터베이스에 동기화 되는 것을 의미

  1. 영속성 컨텍스트 내의 엔티티가 변경이 되어 감지가 되면 스냅샷과 비교를 하여 변경이 된 부분을 찾는다.
  2. 변경이 된 엔티티는 수정 쿼리가 만들어지면서 쓰기 지연 SQL 저장소에 등록이 된다.
  3. 쓰기 지연 SQL 저장소의 쿼리를 DB에 전송한다. 

영속성 컨텍스트 - 플러시의 경우

  1. 직접 호출
    1. flush() 메서드를 직접 호출 - 강제 플러시 진행
    2. TEST, 다른 프레임워크 JPA랑 사용하는 것이 아니면 거의 사용 X
  2. 트랜잭션 커밋 시 플러시 자동호출
    1. 변경 내용이 SQL로 전달되지 않고 틀
  3. JPQL  쿼리 실행 시 플러시 자동 호출
    1. JPQL / Criteria 같은 객체 지향 쿼리를 호출할 때도 플러시 실행

 

준영속

 

영속 → 준영속 상태 변화

 

준영속 상태의 엔티티는 영속성 컨텍스트가 제공하는 기능 사용 불가

 

  1. entitymanager.detach(entity) : 특정 엔티티만 준영속 상태로 전환
  2. entitymanager.clear() : 영속성 컨텍스트를 완전히 초기화
  3. entitymanager.close() : 영속성 컨텍스트를 종료

특징

  • 비영속 상태에 가까움
    • 영속성 컨텍스트의 기능 사용 불가
  • 식별자 값을 가지고 있음
    • 새로 생성이 된 new, 비영속 상태의 경우 식별자 Id값이 없을 수도 있지만 준영속의 경우 영속 상태에서 다시 나온 것이기에 식별자가 존재
  • 지연 로딩을 할 수 없음
    • 지연 로딩 : 연관된 엔티티를 실제 사용할 때 조회
    • 즉시 로딩 : 엔티티를 조회할 때 연관된 엔티티도 함께 조회

 

출처

 

JPA 심화 (notion.site)

 

JPA 심화

[목차]

teamsparta.notion.site

자바 ORM 표준 JPA 프로그래밍 : 네이버 도서 (naver.com)

 

자바 ORM 표준 JPA 프로그래밍 : 네이버 도서

네이버 도서 상세정보를 제공합니다.

search.shopping.naver.com

 

'DataBase > JPA' 카테고리의 다른 글

[JPA]@Transactional이란  (0) 2024.09.24
[ETC] Fetch 옵션  (0) 2023.08.28
[JPA] 엔티티 매핑  (0) 2022.12.21