심화/Spring

[Spring] 영속성 컨텍스트의 기능 (업데이트 중..)

annovation 2025. 10. 14. 22:08
📌 영속성 컨텍스트는 Entity 객체를 효율적으로 쉽게 관리하기 위해 만들어진 공간이다.
영속성 컨텍스트가 어떻게 Entity 객체를 효율적으로 관리하고 있는지 살펴보자.

1차 캐시

 

💡영속성 컨텍스트 내부

영속성 컨텍스트 내부

  • 영속성 컨텍스트는 내부적으로 캐시 저장소를 가지고 있다.
  • Java의 @Entity 클래스의 객체들이 1차 캐시 즉, 캐시 저장소에 저장된다.
  • 이 캐시 저장소는 Map 자료 구조 형태로 되어있다.
    • key에는 @Id로 매핑한 기본키 즉, 식별자 값을 저장한다.
    • value에는 해당 Entity 클래스의 객체를 저장한다.

캐시 저장소 활용

 

영속성 컨텍스트가 이 캐시 저장소를 어떻게 활용하고 있는지 예시를 통해 살펴보자

 

1️⃣ Entity 저장

Entity 저장 예시

  • em.persist(memo); 메서드가 호출되면 memo Entity 객체를 캐시 저장소에 저장한다.

✅ memo 저장 Test 코드

@Test
@DisplayName("1차 캐시 : Entity 저장")
void test1() {
    EntityTransaction et = em.getTransaction();

    et.begin();

    try {

        Memo memo = new Memo();
        memo.setId(1L);
        memo.setUsername("Robbie");
        memo.setContents("1차 캐시 Entity 저장");

        em.persist(memo);

        et.commit();

    } catch (Exception ex) {
        ex.printStackTrace();
        et.rollback();
    } finally {
        em.close();
    }

    emf.close();
}

 

  • em > persistenceContext > entitiesBykey

  • key-value 형태로 정보가 저장되어있음을 확인할 수 있다.

2️⃣ Entity 조회

 

🔎 캐시 저장소에 조회하는 Id가 존재하지 않은 경우

 

1. 캐시 저장소 조회

 

2. DB SELECT 조회 후 캐시 저장소에 저장

  • em.find(Memo.class, 1); 호출 시 캐시 저장소를 확인 한 후 해당 값이 없다면?
  • DB에 SELECT 조회 후 해당 값을 캐시 저장소에 저장하고 반환한다.

✅ memo 조회 Test 코드

@Test
@DisplayName("Entity 조회 : 캐시 저장소에 해당하는 Id가 존재하지 않은 경우")
void test2() {
    try {

        Memo memo = em.find(Memo.class, 1);
        System.out.println("memo.getId() = " + memo.getId());
        System.out.println("memo.getUsername() = " + memo.getUsername());
        System.out.println("memo.getContents() = " + memo.getContents());


    } catch (Exception ex) {
        ex.printStackTrace();
    } finally {
        em.close();
    }

    emf.close();
}
  • DB에서 데이터를 조회만 하는 경우에는 데이터의 변경이 발생하는 것이 아니기 때문에 트랜잭션이 없어도 조회가 가능하다.
  • Memo memo = em.find(Memo.class, 1); 호출 시 캐시 저장소에 해당 값이 존재하지 않기 때문에 DB에 SELECT 조회하여 캐시 저장소에 저장한 후 반환한다.

🔎 캐시 저장소에 조회하는 Id가 존재하는 경우

  • em.find(Memo.class, 1); 호출 시 캐시 저장소에 식별자 값이 1이면서 Memo Entity 타입인 값이 있는지 조회한다.
  • 값이 있다면 해당 Entity 객체를 반환한다.

✅ memo 조회 Test 코드

@Test
@DisplayName("Entity 조회 : 캐시 저장소에 해당하는 Id가 존재하는 경우")
void test3() {
    try {

        Memo memo1 = em.find(Memo.class, 1);
        System.out.println("memo1 조회 후 캐시 저장소에 저장\n");

        Memo memo2 = em.find(Memo.class, 1);
        System.out.println("memo2.getId() = " + memo2.getId());
        System.out.println("memo2.getUsername() = " + memo2.getUsername());
        System.out.println("memo2.getContents() = " + memo2.getContents());


    } catch (Exception ex) {
        ex.printStackTrace();
    } finally {
        em.close();
    }

    emf.close();
}
  • Memo memo1 = em.find(Memo.class, 1); 호출 때는 캐시 저장소에 존재하지 않기 때문에 DB에 SELECT 조회하여 캐시 저장소에 저장한다.
  • Memo memo2 = em.find(Memo.class, 1); 를 호출 했을 때는 이미 캐시 저장소에 해당 값이 존재하기 때문에 DB에 조회하지 않고 캐시 저장소에서 해당 값을 반환한다.

3️⃣ Entity 삭제


출처

https://teamsparta.notion.site/2-9-2252dc3ef514813a93cbcc98fd367b74

 

챕터2-9 : 영속성 컨텍스트의 기능 | Notion

영속성 컨텍스트는 Entity 객체를 효율적으로 쉽게 관리하기 위해 만들어진 공간입니다.

teamsparta.notion.site