흰 스타렉스에서 내가 내리지

[JPA] 영속성 컨텍스트와 JPQL 본문

JPA

[JPA] 영속성 컨텍스트와 JPQL

주씨. 2024. 4. 25. 17:10
728x90

# 영속성 컨텍스트에 이미 엔티티 데이터가 있는데, 이를 다시 JPQL 로 조회하면?

em.find(Member.class, "hong");

em.createQuery("select m from Mmebr m", Member.class).getResultList();

 

 

  • JPQL 로 데이터베이스에서 조회한 엔티티가 영속성 컨텍스트에 이미 있으면, JPQL 로 데이터베이스에서 조회한 결과를 버리고 대신에 영속성 컨텍스트에 있던 엔티티를 반환한다.
    • 이 때, 식별자 값을 사용해서 비교한다. 
    • JPQL 은 항상 데이터베이스에 SQL 을 실행해서 결과를 조회한다.

 

  1. JPQL 을 사용해서 조회를 요청한다
  2. JPQL 은 SQL 로 변환되어 데이터베이스를 조회한다.
  3. 조회한 결과와 영속성 컨텍스트를 비교한다
  4. 식별자 값을 기준으로 member1 은 이미 영속성 컨텍스트에 있으므로 버리고, 기존에 있던 member1 이 반환대상이 된다.
  5. 식별자 값을 기준으로 member2 는 영속성 컨텍스트에 없으므로 영속성 컨텍스트에 추가한다.
  6. 쿼리 결과인 member1, member2 를 반환한다. 여기서 member1 은 쿼리 결과가 아닌 영속성 컨텍스트에 있던 엔티티다.

즉, 영속성 컨텍스트에 이미 존재하는 엔티티가 있으면 기존 엔티티를 반환한다.

 

 

# 왜 DB 에서 새로 조회한 데이터를 버리고 영속성 컨텍스트에 있는 기존 데이터를 반환하는 걸까?

영속성 컨텍스트에 수정 중인 데이터가 사라질 수 있기 때문이다.

?이게 무슨 소리?

 

예시 설명

예를 들어, 데이터베이스에 '사용자' 엔티티가 있고, 특정 사용자의 정보(예: 사용자 이름)를 수정 중이라고 가정해 보자.

  1. 엔티티 조회 및 수정 시작:
    • 사용자 엔티티를 조회하여 영속성 컨텍스트에 로드한다.
    • 사용자 이름을 "Alice"에서 "Bob"로 변경하지만, 아직 데이터베이스에는 반영하지 않았다(트랜잭션이 커밋되지 않음).
  2. 동일 엔티티 재조회:
    • 같은 트랜잭션 내에서 다시 같은 사용자 ID로 엔티티를 조회한다.
    • 이때, JPA는 데이터베이스가 아닌 영속성 컨텍스트를 먼저 확인한다. 이미 영속성 컨텍스트에 해당 사용자의 정보가 있으므로, 데이터베이스에서 새로운 데이터를 가져오지 않고, 기존에 영속성 컨텍스트에 있는 엔티티(수정 중인 "Bob")를 반환한다.
  3. 데이터의 일관성 유지:
    • 만약 JPA가 새로운 데이터를 데이터베이스에서 조회해서 반환한다면, "Bob"라는 중요한 변경사항이 무시되고, 원래 데이터베이스에 저장된 "Alice"가 다시 로드될 것이다.
    • 이는 수정 중인 데이터를 잃어버리게 하며, 데이터의 일관성이 깨질 수 있다.

 

중요성

이 메커니즘은 엔티티의 무결성과 일관성을 유지하는 데 중요하다.

영속성 컨텍스트는 작업 중인 엔티티에 대한 변경사항을 추적하고, 트랜잭션이 종료될 때(커밋 시) 이러한 변경사항을 데이터베이스에 한 번에 반영한다.

이 과정에서 엔티티의 최신 상태를 유지하면서 동시에 데이터베이스와의 불필요한 데이터 교환을 최소화하여 성능을 향상시킬 수 있다.

따라서, 영속성 컨텍스트는 JPA의 핵심 부분으로, 데이터 액세스 계층에서 데이터 일관성과 효율성을 동시에 관리하는 중요한 역할을 한다.