본문 바로가기
Back-End/자바 ORM 표준 JPA 프로그래밍

[JPA] 자바 ORM 표준 JPA 프로그래밍_3장

by ChaSso 2023. 5. 29.

3장 영속성 관리

∘ 엔티티 매니저 : 엔티티를 저장, 수정, 삭제, 조회하는 등 엔티티와 관련된 모든 일을 처리함

∘ '엔티티 매니저 = 엔티티를 저장하는 가상의 데이터베이스'라고 생각하면 됨

 

 

3.1 엔티티 매니저 팩토리와 엔티티 매니저

∘ 엔티티 매니저 팩토리 생성 코드

EntityManagerFactory emf = Persistence.createEntityManagerFactory("jpabook");

 

∘ 엔티티 매니저 팩토리에서 엔티티 매니저 생성

EntityManager em = emf.createEntityManager();

 

∘ 엔티티 매니저 팩토리 : 엔티티 매니저를 만드는 공장

  - 엔티티 매니저 팩토리를 생성하는 데 드는 비용이 크기 때문에 애플리케이션 당 1개만 만들어서 공유해서 사용

  - 엔티티 매니저 팩토리는 여러 스레드가 동시에 접근해도 안전함. 서로 다른 스레드 간에 공유해도 됨.

    엔티티 매니저는 여러 스레드가 동시에 접근하면 동시성 문제 발생함. 스레드 간에 공유하면 안 됨.

∘ 엔티티 매니저는 데이터베이스 연결이 꼭 필요한 시점까지 커넥션을 얻지 않음

 

 

3.2 영속성 컨텍스트란?

∘ 영속성 컨텍스트(persistence context) : 엔티티를 영구 저장하는 환경

  - 엔티티 매니저를 생성할 때 하나 만들어짐

  - 엔티티 매니저를 통해 접근, 관리

∘ 엔티티 매니저로 엔티티를 저장하거나 조회하면 엔티티 매니저는 영속성 컨텍스트에 엔티티를 보관하고 관리

∘ persist() : 엔티티 매니저를 사용해서 회원 엔티티를 영속성 컨텍스트에 저장

 

 

3.3 엔티티의 생명주기

비영속(new/transient) : 영속성 컨텍스트와 전혀 관계가 없는 상태

  - 엔티티 생성 후, 저장 전

 

영속(managed) : 영속성 컨텍스트에 저장된 상태

  - 영속성 컨텍스트가 관리하는 엔티티

  - em.persist()

  - em.find()

 

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

  - 영속 상태의 엔티티를 영속성 컨텍스트가 관리하지 않으면 준영속 상태가 됨

  - em.detach()

 

삭제(removed) : 삭제된 상태

  - 엔티티를 영속성 컨텍스트와 데이터베이스에서 삭제

  - em.remove()

 

 

3.4 영속성 컨텍스트의 특징

∘ 영속성 컨텍스트와 식별자 값

  - 엔티티를 식별자 (@ID로 테이블의 기본 키와 매핑한 값)으로 구

    영속 상태는 식별자 값이 반드시 있어야 함

 

∘ 영속성 컨텍스트와 데이터베이스 저장

  - JPA는 보통 트랜잭션을 커밋하는 순간 영속성 컨텍스트에 새로 저장된 엔티티를 데이터베이스에 반영

 

∘ 영속성 컨텍스트가 엔티티를 관리할 때의 장점

  - 1차 캐시

  - 동일성 보장

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

  - 변경 감지

  - 지연 로딩

 

3.4.1 엔티티 조회

∘ 1차 캐시 : 영속성 컨텍스트가 내부에 가지고 있는 캐시. 모든 영속 상태의 엔티티가 저장되는 곳.

  - 키는 @Id로 매핑한 식별자

  - 식별자 값은 데이터베이스 기본 키와 매핑되어 있음

∘ em.find()를 호출하면 먼저 1차 캐시에서 식별자 값으로 엔티티를 찾음. 1차 캐시에 없으면 데이터베이스에서 조회.

 

1차 캐시에서 조회

∘ em.find()로 엔티티 찾음 → 엔티티가 있으면 1차 캐시에서 엔티티 조회

 

데이터베이스에서 조회

∘ em.find() 호출했는데 엔티티가 1차 캐시에 없음 → 엔티티 매니저가 데이터베이스를 조회해서 엔티티 생성 → 1차 캐시에 저장 → 영속 상태의 엔티티 반환

 

영속 엔티티의 동일성 보장

∘ 같은 식별자로 조회한 인스턴스는 동일한 인스턴스

∘ 영속성 컨텍스트는 성능상 이점과 엔티티의 동일성 보장

 

3.4.2 엔티티 등록

∘ 쓰기 지연 : 엔티티 매니저는 트랜잭션을 커밋하기 전까지 데이터베이스에 엔티티를 저장하지 않고 내부 쿼리 저장소에 INSERT SQL을 모아두고 있다가 트랜잭션을 커밋할 때 모아둔 쿼리를 데이터베이스에 보냄

∘ 트랜잭션 커밋 commit() → 영속성 컨텍스트를 플러시 실제 데이터베이스에 트랜잭션을 커밋

 

트랜잭션을 지원하는 쓰기 지연이 가능한 이유

∘ 트랜잭션을 커밋하기 전까지 쿼리가 반영되지 않음

 

3.4.3 엔티티 수정

SQL 수정 쿼리의 문제점

∘ 발생할 수 있는 모든 상황에 대한 수정 쿼리를 추가하다보면 수정 쿼리의 개수가 많아지고, 비즈니스 로직을 분석하기 위해 SQL을 계속 확인해야 함 ⇒ 비즈니스 로직이 SQL에 의존하게 됨

 

변경 감지

∘ JPA로 엔티티를 수정하려면 단순히 엔티티를 조회해서 데이터만 변경하면 됨

∘ 변경 감지(dirty checking) : 엔티티의 변경사항을 데이터베이스에 자동으로 반영하는 기능

∘ JPA는 엔티티를 영속성 컨텍스트에 보관할 때 최초 상태를 복사해서 저장해둠 (스냅샷)

  플러시 시점에 스냅샷과 엔티티를 비교해서 변경된 엔티티를 찾음

∘ 영속성 컨텍스트가 관리하는 영속 상태의 엔티티에만 적용됨

∘ JPA의 기본 전략은 변경된 부분에 대해서만 수정 쿼리를 생성하지 않고, 엔티티의 모든 필드를 업데이트

∘ 필드가 많거나 저장되는 내용이 너무 크면 수정된 데이터만 사용해서 동적으로 UPDATE SQL을 생성하도록 하면 됨

 

3.4.4 엔티티 삭제

∘ 엔티티 삭제하려면 삭제하려는 엔티티 조회부터 해야 됨

∘ em.remove()

∘ em.remove()를 호출하면 해당 엔티티는 영속성 컨텍스트에서 제거됨 (실제 데이터베이스에서 삭제되는 건 트랜잭션 커밋, 플러시 후)

 

 

3.5 플러시

∘ flush()

∘ 플러시 : 영속성 컨텍스트의 변경 내용을 데이터베이스에 반영

 

∘ 영속성 컨텍스트를 플러시하는 방법

  - 직접 호출

  - 트랜잭션 커밋 시 플러시 자동 호출

  - JPQL 쿼리 실행 시 플러시 자동 호출

 

3.5.1 플러시 모드 옵션

∘ FlushModeType.AUTO : 커밋이나 쿼리를 실행할 때 플러시 (기본값)

FlushModeType.COMMIT : 커밋할 때만 플러시

∘ 동기화 기능

 

 

3.6 준영속

∘ 준영속 상태 : 영속성 컨텍스트가 관리하는 영속 상태의 엔티티가 영속성 컨텍스트에서 분리된 상태

∘ 준영속 상태의 엔티티는 영속성 컨텍스트가 제공하는 기능을 사용할 수 없음

∘ 영속 상태의 엔티티를 준영속 상태로 만드는 방법

  - em.detach(entity)

  - em.clear()

  - em.close()

 

3.6.1 엔티티를 준영속 상태로 전환: detach()

∘ em.detach(entity)를 호출하면 해당 엔티티를 관리하기 위한 모든 정보가 제거됨

∘ 준영속 상태 : 영속 상태였다가 더는 영속성 컨텍스트가 관리하지 않는 상태

 

3.6.2 영속성 컨텍스트 초기화: clear()

∘ em.clear() : 영속성 컨텍스트를 초기화해서 해당 영속성 컨텍스트의 모든 엔티티를 준영속 상태로 만듦

 

3.6.3 영속성 컨텍스트 종료: close()

∘ 영속성 컨텍스트를 종료하면 해당 영속성 컨텍스트의 영속 상태의 엔티티가 모두 준영속 상태가 됨

 

3.6.4 준영속 상태의 특징

∘ 거의 비영속 상태에 가까움

∘ 식별자 값을 가지고 있음

∘ 지연 로딩을 할 수 없음

  - 지연 로딩(LAZY LOADING) : 실제 객체 대신 프록시 객체를 로딩해두었다가 해당 객체를 실제로 사용할 때 영속성 컨텍스트를 통해 데이터를 불러오는 방법. 영속 상태일 때 사용.

 

3.6.5 병합: merge()

∘ 준영속 상태의 엔티티를 다시 영속 상태로 변경할 때 병합 사용

∘ merge()는 준영속 상태의 엔티티로부터 얻은 정보로 새로운 영속 상태의 엔티티를 반환

 

준영속 병합

비영속 병합

 

 

3.7 정리

∘ 엔티티 매니저는 엔티티 매니저 팩토리가 생성

∘ 엔티티 매니저가 만들어지면 그 내부에 영속성 컨텍스트가 만들어짐

∘ 영속성 컨텍스트는 엔티티 매니저를 통해서 접근

∘ 영속성 컨텍스트는 1차 캐시, 쓰기 지연 등의 기능을 제공

∘ 일반적으로 트랜잭션을 커밋할 때 영속성 컨텍스트가 플러시됨

∘ 영속, 더 이상 관리하지 않으면 준영속

준영속 상태의 엔티티는 영속성 컨텍스트의 기능을 사용할 수 없음