본문 바로가기
Java/JPA

[SpringBoot_JPA_Basic] JPA 1차 cache

by HJ0216 2023. 6. 16.

이 글은 김영한의 [자바 ORM 표준 JPA 프로그래밍 - 기본편] 수강하며 정리한 글입니다.

 

 

🟦 기본 환경: IDE: IntelliJ, Language: Java

 

 

1차 cache

: EntityManager가 관리하는 영속성 컨텍스트(Persistence Context) 내부에 있는 첫 번째 캐시

 

비영속상태

: Entity Manager에 의해 관리되지 않는 상태

 

영속상태

: Entity Manager에 의해 관리되는 상태

 

 

⭐ 영속성 컨텍스트에 저장 ≠ DB에 저장

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
32
33
34
35
36
37
38
39
40
package jpa_basic;
 
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import java.util.List;
 
public class Main {
    public static void main(String[] args) {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
 
        EntityManager em = emf.createEntityManager();
 
        EntityTransaction tx = em.getTransaction();
        tx.begin(); // transaction 시작 선언
 
        try {
            // 비영속: Entity Manager와 무관
            Member member = new Member();
            member.setId(100L);
            member.setName("HelloJPA");
 
            // 영속
            System.out.println("BEFORE");
            em.persist(member); // 1차 cache 저장
            System.out.println("AFTER");
 
            tx.commit(); // commit 후, DB 저장
        } catch (Exception e) {
            tx.rollback();
        } finally {
            em.close();
        }
 
        emf.close();
 
    }
}
 
 
 

결과

1
2
3
4
5
6
7
8
9
10
11
BEFORE
AFTER
Hibernate: 
    /* insert jpa_basic.Member
        */ insert 
        into
            Member
            (name, id) 
        values
            (?, ?)
 
 

⭐ BEFORE 출력 em.persist → AFTER 출력 → DB 저장(insert query)

 

 

1차 CACHE 조회(1)

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
32
33
34
35
36
37
38
39
40
41
42
43
package jpa_basic;
 
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import java.util.List;
 
public class Main {
    public static void main(String[] args) {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
 
        EntityManager em = emf.createEntityManager();
 
        EntityTransaction tx = em.getTransaction();
        tx.begin(); // transaction 시작 선언
 
        try {
            // 비영속: Entity Manager와 무관
            Member member = new Member();
            member.setId(101L);
            member.setName("HelloJPA");
 
            // 영속
            em.persist(member); // 1차 cache 저장
 
            Member findMember = em.find(Member.class, 101L);
            // 1차 cache에 저장된 동일한 PK로 값을 조회하므로 DB에 select을 사용하지 않고도 findMember가 가능
            System.out.println("findMember.id: " + findMember.getId());
            System.out.println("findMember.name: " + findMember.getName());
 
            tx.commit(); // commit 후, DB 저장
        } catch (Exception e) {
            tx.rollback();
        } finally {
            em.close();
        }
 
        emf.close();
 
    }
}
 
 
 

결과

1
2
3
4
5
6
7
8
9
10
11
findMember.id: 101
findMember.name: HelloJPA
Hibernate: 
    /* insert jpa_basic.Member
        */ insert 
        into
            Member
            (name, id) 
        values
            (?, ?)
 
 

⭐ DB에 insert query 전 데이터 조회 가능

: persist ▶ persistence context의 1차 cache에 저장 ▶ find()  가장 먼저 1차 캐시 검색

: Main App 실행 시, persist()를 통해 1차 캐시에 저장된 값과 find()로 조회하고자하는 대상(매개변수 PK)이 같다면 같은 transaction 안에서 같은 영속성 컨텍스트로 관리되는 상태이므로 1차 캐시에서 조회할 수 있음

 

 

1차 CACHE 조회(2)

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
32
33
package jpa_basic;
 
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import java.util.List;
 
public class Main {
    public static void main(String[] args) {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
 
        EntityManager em = emf.createEntityManager();
 
        EntityTransaction tx = em.getTransaction();
        tx.begin(); // transaction 시작 선언
 
        try {
            Member findMember = em.find(Member.class, 101L);
            Member findMember = em.find(Member.class, 101L);
 
            tx.commit();
        } catch (Exception e) {
            tx.rollback();
        } finally {
            em.close();
        }
 
        emf.close();
 
    }
}
 
 
 

결과

1
2
3
4
5
6
7
8
9
Hibernate: 
    select
        member0_.id as id1_0_0_,
        member0_.name as name2_0_0_ 
    from
        Member member0_ 
    where
        member0_.id=?
 
 
 

⭐ 1차 캐시가 빈 상태에서 같은 대상을 조회할 경우, select query가 1개밖에 존재하지 않음

: find() ▶ 1차 캐시 조회 ▶ DB 조회 ▶1차 캐시에 저장

: member1 - 1차 캐시에 조회할 데이터가 없으므로 DB로 select query 실행

: member2 - member1 조회한 데이터 값이 1차 캐시에 저장되었으므로 1차 캐시에서 데이터 조회(select query 발생 X)

 

 

 

참고 자료

 

JPA - 영속성(persistence란) [+1차 캐시]

영속성 Spring JPA 로고를 보면 영속성(persistence)라는 단어가 크게 그려져 있습니다. 그만큼, 영속성 없이 Spring JPA를 얘기하기 힘듭니다. 영속성은 쉽게 말하면 지속을 의미합니다. 더 자세히 풀자

jaehoney.tistory.com

 

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

[JPA] @PrePersist  (0) 2023.06.25
[JPA] JOIN Null값 처리  (0) 2023.06.20
[JPA_Basic] JPA persist, find, remove, update  (0) 2023.06.15
[SpringBoot_JPA_1] @PathVariable  (0) 2023.06.03
[SpringBoot_JPA_1] TypedQuery  (0) 2023.06.02