영속성 컨텍스트는 엔티티를 영구 저장하고 관리하는 논리적인 공간입니다. 애플리케이션은 EntityManager를 통해 영속성 컨텍스트에 접근하며, 일반적인 Spring 환경에서는 트랜잭션 범위 안에서 하나의 영속성 컨텍스트를 사용합니다.
영속성 컨텍스트는 식별자를 키로 엔티티를 보관하는 1차 캐시를 가집니다. 같은 영속성 컨텍스트에서 동일한 식별자의 엔티티를 다시 조회하면 1차 캐시에 있는 동일한 객체를 반환하므로 엔티티의 동일성을 보장합니다. 단, 1차 캐시는 보통 트랜잭션 범위에 한정되므로 여러 요청에서 공유되는 애플리케이션 캐시는 아닙니다.
또한 트랜잭션 안에서 엔티티의 변경 전 상태를 스냅샷으로 보관하고, 플러시 시점에 현재 상태와 비교하여 UPDATE SQL을 생성하는 변경 감지를 지원합니다. INSERT SQL을 모아 플러시 시점에 데이터베이스로 보내는 쓰기 지연도 지원하므로 SQL 실행 시점을 조정하거나 일부 쿼리를 묶어 처리할 수 있습니다.
결과적으로 영속성 컨텍스트는 1차 캐시, 동일성 보장, 변경 감지, 쓰기 지연을 통해 객체와 데이터베이스 사이의 상태를 일관되게 관리합니다.
영속성 컨텍스트와 데이터베이스를 동기화하는 시점은 언제인가요?
트랜잭션 커밋 직전이나 JPQL 쿼리 실행 전, 또는
EntityManager.flush()를 직접 호출할 때 플러시가 발생합니다. 플러시는 SQL을 데이터베이스에 전달하는 과정이며 트랜잭션 커밋 자체를 의미하지는 않습니다.
같은 엔티티를 두 번 조회하면 항상 데이터베이스 쿼리가 한 번만 실행되나요?
같은 영속성 컨텍스트에서 식별자로 조회했다면 1차 캐시를 사용하므로 보통 한 번만 실행됩니다. 하지만 서로 다른 영속성 컨텍스트이거나 JPQL 조회처럼 쿼리 실행 자체가 필요한 경우에는 SQL이 실행될 수 있습니다.
영속성 컨텍스트를 초기화하면 어떻게 되나요?
clear()를 호출하면 관리 중인 모든 엔티티가 준영속 상태가 되고 1차 캐시와 변경 감지 정보가 사라집니다. 아직 플러시하지 않은 변경 사항도 반영되지 않을 수 있으므로 필요한 경우flush()후clear()해야 합니다.