티스토리 뷰
영속성 컨텍스트
영속성 컨텍스트란, 엔티티를 영구 저장하는 환경이라는 뜻이다. EntityManager
의 persist()
를 사용하여, Entity를 DB에 저장하고 영속성 컨텍스트로 관리한다. 이러한 영속성 컨텍스트는 논리적인 개념이기 때문에 눈에 보이지 않고, EntityManager
를 통해서 접근한다.
엔티티의 생명주기
엔티티의 생명주기는 다음과 같이 총 4단계
로 구성된다.
비영속(new/transient)
비영속이란, 영속성 컨텍스트와 전혀 관계가 없는 새로운 상태를 말한다.
// 객체만 생성하였으므로, 비영속 상태
Member member = new Member();
member.setEmail("shyune@knou.ac.kr");
member.setUsername("hyuuny");
영속(managed)
영속이란, 영속성 컨텍스트에 관리되는 상태를 말한다.
// 아직은 비영속 상태
Member member = new Member();
member.setEmail("shyune@knou.ac.kr");
member.setUsername("hyuuny");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin(); // 트랜잭션 시작!
// 객체를 저장한 상태(영속)
// 영속성 컨텍스트가 관리하는 객체가 된다.
em.persist(member);
준영속(detached)
준영속이란, 영속성 컨텍스트에 저장되었다가 분리된 상태를 말한다.
// 회원 엔티티를 영속성 컨텍스트에서 분리, 준영속 상태
em.detach(member);
삭제(removed)
말 그대로 삭제된 상태를 말한다.
// 객체를 삭제한 상태(삭제)
em.remove(member);
1차 캐시
영속성 컨텍스트는 내부에 1차 캐시를 갖고 있다. 1차 캐시는 Transaction
내에서만 효과가 있기 때문에, Transaction이 끝나면 사라진다.
// 엔티티를 생성한 상태(비영속)
Member member = new Member();
member.setId(1L);
member.setUsername("hyuuny");
// 엔티티를 영속화
em.persist(member);
- 객체를 저장하면 영속성 컨텍스트에 의해 관리된다.
Member member = new Member();
member.setId(1L);
member.setUsername("hyuuny");
// 1차 캐시에 저장됨
em.persist(member);
// 1차 캐시에서 조회
Member findMember = em.find(Member.class, 1L);
- Id값 1L로 member 객체를 조회(find)하면 DB에 요청하지 않고, 1차캐시에서 조회한다.
Member findMember = em.find(Member.class, 2L);
- Id값 2L인 member 객체는 1차 캐시에 없으므로, DB에서 값을 조회한다.
동일성(identity) 보장
JPA는 식별자(pk)가 같으면 항상 true이다. 1차 캐시로 반복 가능한 읽기(REPEATABLE READ) 등급의 트랜잭션 격리 수준을 데이터베이스가 아닌 애플리케이션 차원에서 제공한다.
Member m1 = em.find(Member.class, "member1");
Member m2 = em.find(Member.class, "member1");
System.out.println(m1 == m2); // true
트랜잭션을 지원하는 쓰기 지연(transaction write-behind)
JPA는 엔티티를 등록할 때, Insert Query를 보내지 않고 모아두었다가 transaction.commit하는 순간 데이터베이스에 Insert Query를 보낸다.
EntityManager em = emf.createEntityManager();
EntityTransaction transaction = em.getTransaction();
// 엔티티 매니저는 데이터 변경시 트랜잭션을 시작해야 한다.
transaction.begin(); // 트랜잭션 시작
em.persist(memberA);
em.persist(memberB);
// 여기까지 Insert Query를 DB에 보내지 않는다.
// 커밋하는 순간, DB에 Insert Query를 보낸다.
transaction.commit(); // 트랜잭션 커밋
- Insert Query를 바로 보내지 않고 쓰기 지연 SQL 저장소에 모아둔다.
- 쓰기 지연 SQL 저장소에 저장된 Query를 commit 시점에 DB에 보낸다.
변경 감지(Dirty Checking)
JPA는 Transaction commit 시점에 엔티티(커밋 시점 객체)와 스냅샷(최초에 DB에서 읽어온 객체)을 비교하여 서로 다를 경우, Update Query를 DB에 반영한다.
EntityManager em = emf.createEntityManager();
EntityTransaction transaction = em.getTransaction();
transaction.begin(); // 트랜잭션 시작
// 영속 엔티티 조회
Member memberA = em.find(Member.class, "memberA");
// 영속 데이터 수정
memberA.setUsername("Lee");
memberA.setAge(10);
// commit 시점에 DB에 Update Query를 보낸다.
transaction.commit(); // 트랜잭션 커밋
'JPA' 카테고리의 다른 글
[JPA] 객체와 테이블 매핑 (0) | 2022.01.24 |
---|---|
[JPA] 준영속 상태(detach) (0) | 2022.01.19 |
[JPA] 플러시(flush) (0) | 2022.01.19 |
- Total
- Today
- Yesterday
- 코테
- 파이썬
- 스프링 부트
- 인프런
- 스프링
- Real MySQL
- 정렬
- 문자열
- mysql 8.0
- MySQL
- 그리디
- leetcode
- spring boot
- webflux
- 북클럽
- 코틀린
- 알고리즘
- 자료구조
- Algorithm
- 스프링부트
- 김영한
- 구현
- 데이터베이스
- 노마드코더
- kotlin
- Spring
- 백준
- 릿코드
- 노마드
- 리팩토링
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |