영속성 관리 - 내부 동작 방식
자바 ORM 표준 JPA 프로그래밍 - 기본편 수업을 듣고 정리한 내용입니다.
📚 1. 영속성 컨텍스트
🔔 JPA에서 가장 중요한 2가지
- 객체와 관계형 데이터베이스 매핑하기(
ORM
) : DB, 객체 등 설계와 관련된 부분이다.
- 영속성 컨텍스트 : 실제
JPA
가 내부적으로 어떻게 동작하는지와 관련된 부분
🔔 JPA에서 가장 중요한 2가지
- 객체와 관계형 데이터베이스 매핑하기(
ORM
) : DB, 객체 등 설계와 관련된 부분이다. - 영속성 컨텍스트 : 실제
JPA
가 내부적으로 어떻게 동작하는지와 관련된 부분
✔️ 엔티티 매니저 팩토리와 엔티티 매니저
JPA
를 사용하기 위해서는 엔티티 매니저 팩토리와 앤티티 매니저에 대해 알아야 한다.- 웹 애플리케이션이 실행될 때
EntityManagerFactory
가 생성된다. - 클라이언트의 요청이 올 때마다
EntityManage
를 생성하여 커넥션 풀을 사용해서 DB에 접근한다.
📣 영속성 컨텍스트
- JPA를 이해하는데 가장 중요한 용어
- 뜻 : “엔티티를 영구 저장하는 환경”
EntityManager.persist(entity);
: 영속성 컨텍스트에 엔티티를 저장한다는 것이다.- 영속성 컨텍스트는 논리적인 개념이며 눈에 보이지 않는다.
- 엔티티 매니저를 통해서 영속성 컨텍스트에 접근한다.
📖 A. 엔티티의 생명주기
- 비영속 (
new/transient
) : 영속성 컨텍스트와 전혀 관계가 없는 새로운 상태 - 영속 (
managed
) : 영속성 컨텍스트에 관리되는 상태 - 준영속 (
detached
) : 영속성 컨텍스트에 저장되었다가 분리된 상태 - 삭제 (
removed
) : 삭제된 상태
✔️ 비영속
JPA
에 관계없이 그냥 객체 생성, 초기화만 된 상태
✔️ 영속
- 엔티티 매니저를 통해 영속성 컨텍스트에 접근한다.
- 영속 상태가 된다고 해서 바로 DB에 쿼리가 날라가는 것은 아니다. → 이후에 커밋해야 저장된다.
✔️ 준영속, 삭제
- 준영속 : 영속성 컨텍스트에서 삭제하는 것
- 삭제 : 실제로 DB에서 해당 ROW를 삭제하는 것
📖 B. 영속성 컨텍스트의 이점
- 1차 캐시
- 동일성(
identity
) 보장- 트랜잭션을 지원하는 쓰기 지연 (
transactional write-behind
)- 변경 감지(
Dirty Checking
)- 지연 로딩(
Lazy Loading
)
(1) 엔티티 조회, 1차 캐시
member
객체를 생성하고persist
하면 영속성 컨텍스트 내부의 1차 캐시에 저장된다.- 이 때
key-value로
저장되며,key
는member1
,value
는member
객체가 담긴다.
✔️ 1차 캐시에서 조회
JPA
는 엔티티 조회할 때 1차 캐시부터 찾는다.- 1차 캐시에서 해당되는 키값을 가진 엔티티가 있다면, 1차 캐시에서 조회해온다.
✔️ 데이터베이스에서 조회
- 1차 캐시에 없으면 DB에서 조회해서
member2
객체를 1차 캐시에 저장한다. - 그 다음
member2
를 반환한다.
(2) 영속 엔터티의 동일성 보장
- 1차 캐시로 반복 가능한 읽기(
REPEATABLE READ
) 등급의 트랜잭션 격리 수준을 데이터베이스가 아닌 애플리케이션 차원에서 제공
(3) 엔티티 등록 트랜잭션을 지원하는 쓰기 지연
EntityManager em = emf.createEntityManager();
EntityTransaction transaction = em.getTransaction();
//엔티티 매니저는 데이터 변경시 트랜잭션을 시작해야 한다.
transaction.begin(); // [트랜잭션] 시작
em.persist(memberA);
em.persist(memberB);
//여기까지 INSERT SQL을 데이터베이스에 보내지 않는다.
//커밋하는 순간 데이터베이스에 INSERT SQL을 보낸다.
transaction.commit(); // [트랜잭션] 커밋
JPA
는 커밋할 때INSERT SQL
을 보낸다.
em.persist(memberA);
로memberA
를 1차 캐시에 넣는다.- 1차 캐시에 저장됨과 동시에
JPA
가 해당 엔티티를 분석해서INSERT SQL
생성해서 쓰기 지연SQL
저장소에 쌓아둔다. em.persist(memberB);
도 동일하게, 1차 캐시에 넣고INSERT SQL
생성해서 쓰기 지연SQL
저장소에 쌓아둔다.
transaction.commit();
하는 시점에 쓰기 지연 SQL
저장소에 쌓인 SQL
문들이 한꺼번에 날아간다. (flush
)
✏️ 쓰기 지연을 사용하는 이유
- 버퍼링 기능으로 인해 쿼리를 여러 번 날리지 않고 최적화가 가능하기 때문이다!
(4) 엔티티 수정 - 변경 감지(Dirty Checking)
EntityManager em = emf.createEntityManager();
EntityTransaction transaction = em.getTransaction();
transaction.begin(); // [트랜잭션] 시작
// 영속 엔티티 조회
Member memberA = em.find(Member.class, "memberA");
// 영속 엔티티 데이터 수정
memberA.setUsername("hi");
memberA.setAge(10);
//em.update(member) 이런 코드가 있어야 하지 않을까?
transaction.commit(); // [트랜잭션] 커밋
transaction.commmit();
을 하면 내부적으로 flush
가 실행된다.
→ 엔티티와 스냇샷을 비교해서 변경된 데이터를 감지한다.
(스냅샷: 엔티티 값을 읽어 온 최초 시점의 엔티티 데이터)
→ 변경 사항이 있다면 UPDATE SQL
을 쓰기 지연 SQL 저장소 쌓아둔다.
→ 쓰기 지연 SQL 저장소의 UPDATE SQL
을 DB에 반영하고 커밋한다.
(5) 엔티티 삭제
//삭제 대상 엔티티 조회
Member memberA = em.find(Member.class, “memberA");
em.remove(memberA); //엔티티 삭제
📚 2. 플러시(Flush)
영속성 컨텍스트의 변경내용을 데이터베이스에 반영하는 것
➡️ 영속성 컨텍스트의 쿼리들을 데이터베이스에 날리는 것이다!
영속성 컨텍스트의 변경내용을 데이터베이스에 반영하는 것
➡️ 영속성 컨텍스트의 쿼리들을 데이터베이스에 날리는 것이다!
✔️ 플러시 발생
- 변경 감지가 발생한다.
- 수정된 엔티티 쓰기 지연 SQL 저장소에 등록한다.
- 쓰기 지연 SQL 저장소의 쿼리를 데이터베이스에 전송 (등록, 수정, 삭제 쿼리)한다.
✔️ 영속성 컨텍스트를 플러시하는 방법
em.flush()
: 직접 호출- 트랜잭션 커밋 : 플러시 자동 호출
JPQL
쿼리 실행 : 플러시 자동 호출
✔️ JPQL 쿼리 실행시 플러시가 자동으로 호출되는 이유
em.persist(memberA);
em.persist(memberB);
em.persist(memberC);
//중간에 JPQL 실행
query = em.createQuery("select m from Member m", Member.class);
List<Member> members= query.getResultList();
JPA
에서는JPQL
쿼리를 수행하기 전에flush
를 실행해서 DB와 영속성 컨텍스트간에 동기화를 해준다.- 등록한
member
들이 조회가 안되는 경우를 막는다.
- 등록한
✔️ 플러시 모드 옵션
em.setFlushMode(FlushModeType.COMMIT)
FlushModeType.AUTO
: 커밋이나 쿼리를 실행할 때 플러시 (기본 값)FlushModeType.COMMIT
: 커밋할 때만 플러시
✏️ 플러시 정리
- 영속성 컨텍스트를 비우지 않는다.
- 영속성 컨텍스트의 변경내용을 데이터베이스에 동기화
- 트랜잭션이라는 작업 단위가 중요하다. → 커밋 직전에만 동기화 하면 된다.
📚 3. 준영속 상태
- 영속 → 준영속
- 영속 상태의 엔티티가 영속성 컨텍스트에서 분리(
detached
)
- 영속성 컨텍스트가 제공하는 기능을 사용 못한다.
detached
)
✔️ 준영속 상태로 만드는 방법
em.detach(entity)
: 특정 엔티티만 준영속 상태로 전환em.clear()
: 영속성 컨텍스트를 완전히 초기화em.close()
: 영속성 컨텍스트를 종료
참고
Author And Source
이 문제에 관하여(영속성 관리 - 내부 동작 방식), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@chang626/영속성-관리-내부-동작-방식저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)