[JPA] Entity는 영속성 컨텍스트에 저장/조회한다!

2023. 1. 25. 01:53·JAVA/Application

🪄 Intro

이 포스팅은 단일 트랜잭션 실습 중 생긴 의문점을 해결한다.

영속성 컨텍스트의 '1차캐시' 개념을 알게 되었다.

 

 


🚨 상황

- Spring JPA를 통한 @Transactional 테스트코드 실습중!

 

↓ 내 테스트코드

Entity의 속성값 "YEEUN KIM"을 "SIKYONG SUNG"으로 변경하는 코드

@Test
@Transactional  // 영속성 컨텍스트 안에서 관리한다.
void UPDATE_TEST() {
    // Given : 엔티티를 영속성 컨텍스트에 저장
    CustomerEntity customer = new CustomerEntity();
    customer.setId(1L);
    customer.setFirstName("YEEUN");
    customer.setLastName("KIM");
    repository.save(customer);

    // When : 엔티티 값 변경
    CustomerEntity entity = repository.findById(1L).get();
    log.info("{} {}", entity.getFirstName(), entity.getLastName()); // 변경 전 값이 찍힌다
    entity.setFirstName("SIKYONG");
    entity.setLastName("SUNG");

    CustomerEntity updated = repository.findById(1L).get();
    log.info("{} {}", updated.getFirstName(), updated.getLastName()); // 변경 후 값이 찍힌다
}

 

 

🚨의문 & 상황검토

 

아래 로그를 보고 의문에 휩싸였다.

 

중간에 값을 변경하고 로그를 찍었더니 변경한 값(SIKYONG SUNG)이 나왔다. 이건 commit된 값이 아니지 않나? 왜 변경한 값이 찍히지?

 

① commit 안한 값을 읽었어??

- 엔티티 값을 "SIKYONG SUNG"으로 업데이트했다.

- 그러나 @Transaction 메서드가 아직 완료되지 않았으므로 "SIKYONG SUNG"은 commit되지 않은 값이 아닌가? 그런데 어째서 이게 read되는 걸까?

 

 

② 현재 격리수준은??

내 상황을 검토해보았다.

- 나는 격리수준이 read commited인 H2 DB를 사용하고 있다.

- @Transactional을 통해 영속성 컨텍스트에서 관리되고 있다.

- @Transactional의 격리 수준은 default이다. 즉 사용하는 DB의 격리수준을 따른다.

- 따라서 현재 격리수준은 read commited 이다.

 

 

위 의문은 "영속성 컨텍스트"를 이해하면 해결된다!

 

 

 

🍒 해답

일단 의문에 코멘트를 달자면.. 

 

① commit 안한 값을 읽었어??

=> 맞다.

=> 근데 애초에 select할 때 DB에서 값을 읽는 게 아니다.

=> "영속성 컨텍스트의 1차캐시"에서 읽어옴을 알아야 한다.

 

② 현재 격리수준은??

=> (언급했듯) read commited

=> 단일 트랜잭션 실습일뿐만 아니라, 어차피 트랜잭션 내에서 Entity 생성하고 업뎃하고 다 하고 있다. 그래서 이 문제에서 격리수준은 딱히 신경 쓸 필요 없어보인다.

 

 

 

그래서 해답은 "영속성 컨텍스트의 1차 캐시"를 이해하는 것에 있다.

 

∨ 조회할 때는 DB가 아닌 1차캐시에서 먼저 조회한다.

- 조회시 1차캐시에 객체가 있는지 확인(PK로 확인)하고, 있다면 가져오기

- 1차캐시에 없다면 2차캐시에서 조회한다.

- 2차캐시에도 없다면 DB에서 조회하여 객체의 스냅샷를 가져온다. 그 스냅샷을 1차2차캐시에 저장한다.

 

∨ 저장하거나 수정할 때도 1차캐시에 변경사항을 저장한다.

 

∨ 참고) 위와 같은 쿼리들은 '내부의 쿼리 저장소'에 일단 저장되고, 최종적으로 트랜잭션 커밋시 한번에 수행되고 나서 DB에 반영된다. 참고로 이는 영속성 컨텍스트의 '쓰기 지연' 특징이다. 여기서는 다루지 않겠음.

 

 

 

🍒 코드 한줄한줄을 영속성 컨텍스트 기반으로 설명해보자.

참고) 아래에서 '영속성 컨텍스트에서 찾는다'라는 표현은,

영속성 컨텍스트의 1차캐시 or 2차 캐시에서 찾는다는 말이다.

 

 

▼ Entity를 만든다. 아직 비영속 상태의 Entity다.

CustomerEntity customer = new CustomerEntity();
customer.setId(1L);
customer.setFirstName("YEEUN");
customer.setLastName("KIM");

 

▼ 영속성 컨텍스트에 Entity를 save한다. 영속 상태의 Entity다.

repository.save(customer);
더보기

Entity를 save할 때 영속성 컨텍스트에서 관리된다.

참고로 save(Entity)할 때 Entity의 PK가 있으면 save, 없으면 update 쿼리가 나간다

 

▼ findById(PK)를 통하여 영속성 컨텍스트에서 해당 PK를 가진 객체를 찾아 가져온다.

CustomerEntity entity = repository.findById(1L).get();

 

▼ Entity를 update하게 되면, 변경 사항이 영속성 컨텍스트에 반영된다.

entity.setFirstName("SIKYONG");
entity.setLastName("SUNG");

 

▼ findById(PK)를 통하여 영속성 컨텍스트에서 해당 PK를 가진 객체를 가져온다.

CustomerEntity updated = repository.findById(1L).get();

 

 

아핫 이제 이해가 된다.

영속성 컨텍스트에 저장한다는 그 개념!

 

 


🍒 이로써 의문 해결!

 

처음에는 "왜 commit되지 않은 값을 읽은거야! read commited잖아!!" 라고 생각하면서 아래 로그를 의아해했지만 이제는 이해할 수 있다. commit과 상관 없다.

Entity는 영속 상태로서, 영속성 컨텍스트의 1차캐시에 반영되고, 1차캐시에서 읽어오기 때문이다!

 

 

 


공부에 도움이 된 글:

https://blog.neonkid.xyz/233

 

[Spring] JPA 영속성 컨텍스트 구조로 보는 이점

지난 포스트에서 JPA의 영속성 컨텍스트와 생명 주기에 대해 알아봤습니다. 간단하게 영속성 컨텍스트의 생명 주기의 관계를 통해서 Java로 구현된 객체가 어떻게 DB로 적재되고 삭제되는지를 알

blog.neonkid.xyz

https://www.blog.ecsimsw.com/entry/JPA-%EC%98%81%EC%86%8D%EC%84%B1-%EC%BB%A8%ED%85%8D%EC%8A%A4%ED%8A%B8-1%EC%B0%A8-%EC%BA%90%EC%8B%9C-%EC%93%B0%EA%B8%B0-%EC%A7%80%EC%97%B0

 

JPA / 영속성 컨텍스트 / 1차 캐시 / 쓰기 지연

"T아카데미 / JPA 프로그래밍 기본기 다지기 - 김영한 " 강좌를 듣고 정리한 글입니다. 영속성 컨텍스트를 영속성 컨텍스로 관리하면 어떤 이점을 갖을까 1. 1차 캐시 / 엔티티 동일성 보장 2. 쓰기

www.blog.ecsimsw.com

 

반응형

'JAVA > Application' 카테고리의 다른 글

[자바/스프링] 데이터 액세스 층 설계  (1) 2023.08.11
[Springboot] thymeleaf-extras-springsecurity5 dependency 못 읽어오는 문제  (1) 2023.02.03
Springboot Mybatis 사용해보기 ─ xml 파일로 쿼리문 관리  (0) 2023.01.23
Spring MVC | Controller는 어떻게 요청을 처리하는 걸까? | Controller와 Servlet  (0) 2023.01.19
Spring AOP 쉽게 이해하기 | 그리고 간단한 예제코드  (0) 2023.01.16
'JAVA/Application' 카테고리의 다른 글
  • [자바/스프링] 데이터 액세스 층 설계
  • [Springboot] thymeleaf-extras-springsecurity5 dependency 못 읽어오는 문제
  • Springboot Mybatis 사용해보기 ─ xml 파일로 쿼리문 관리
  • Spring MVC | Controller는 어떻게 요청을 처리하는 걸까? | Controller와 Servlet
히어로맛쿠키
히어로맛쿠키
  • 히어로맛쿠키
    yeny_lab
    히어로맛쿠키
  • 전체
    오늘
    어제
    • 분류 전체보기 (388)
      • 미분류글 (30)
        • ㅇ (2)
      • JAVA (84)
        • Effective Java (1)
        • Application (21)
      • 컴퓨터구조 & OS (29)
      • 자료구조 + 알고리즘 (43)
      • Database (12)
      • 컴파일러 (10)
      • 수학 (33)
        • 미분방정식 (12)
      • 데이터분석과 머신러닝 (38)
      • 기타 (58)
      • yyeeennyy (25)
  • 최근 글

  • hELLO· Designed By정상우.v4.10.4
히어로맛쿠키
[JPA] Entity는 영속성 컨텍스트에 저장/조회한다!
상단으로

티스토리툴바