본문 바로가기
카테고리 없음

영속성 컨텍스트와 엔티티 매니저

by 장코딩 2025. 2. 11.

엔티티 매니저란?

JPA에서 엔티티를 관리하는 것으로, 영속성 컨텍스트에 접근하여 엔티티에 대한 DB 작업을 제공한다.
기본적으로 한 요청 당 하나의 EntityManager를 사용하며, 각 EntityManager는 정해진 영속성 컨텍스트를 참조하게 된다.

 

영속성 컨텍스트란?

엔티티를 영구 저장하는 환경으로, 엔티티 매니저를 통해 엔티티를 영속성 컨텍스트에 보관하고 관리한다.
애플리케이션과 DB 사이에 객체를 보관하는 가상의 DB이다.

 

Spring에서는 EntityManager는 요청마다 생성되므로 다수 존재하고, 영속성 컨텍스트는 1개 존재한다.

따라서 EntityManager와 영속성 컨텍스트는 N:1

 

 

영속성 상태

1. 영속 (persist)

엔티티가 영속성 컨텍스트에 저장된다.

영속성 컨텍스트 1차 캐시에 저장되며, JPA가 엔티티를 분석해 Insert 쿼리를 생성하여 쓰기 지연을 수행하도록 쿼리문을 저장해둔다.

 

2. 준영속 (detach)

엔티티가 영속성 컨텍스트에 저장되었다가 분리된 상태. (영속 → 준영속)

영속성 컨텍스트가 엔티티를 관리하지 않는 상태이므로, 영속성 컨텍스트가 제공하는 기능을 사용하지 못한다.

 

그 밖에 영속성 컨텍스트를 초기화 시키는 clear()와 영속성 컨텍스트를 종료시키는 close()도 존재한다.

 

3. 삭제 (removed)

영속성 컨텍스트에 있는 엔티티를 삭제한다.

이때 DB에서도 삭제 됨.

 

엔티티를 영속성 컨텍스트에 왜 저장할까?

1. 1차 캐시

엔티티 매니저가 트랜잭션 단위로 Map 구조의 캐시를 만드는데, 이 캐시가 살아있는 트랜잭션 동안 find를 하면 1차 캐시를 먼저 조회하고, 없으면 DB에서 조회한다.

Member member = new Member();
member.setId("member1");
member.setUsername("회원1");

// 1차 캐시에 저장
em.persist(member);

// 1차 캐시에서 조회
Member findMember = em.find(Member.class, "member1");

 

2. 동일성 보장

같은 트랜잭션 안에서 같은 객체는 == 비교 보장

 

3. 트랜잭션을 지원하는 쓰기 지연

한 트랜잭션 안에서 DB에 보낼 쿼리문을 영속성 컨텍스트 안에 모았다가 한번에 보낸다.

쿼리문은 트랜잭션이 끝나기 전 (commit())과 em.flush()에서 보내게 된다.

네트워크 부하를 줄이기 위해 사용된다.

 

(flush(): 영속성 컨텍스트의 변경 내용을 데이터베이스에 반영하는 것. 트랜잭션 commit, JPQL 쿼리 실행의 경우 발생된다.)

4. 변경 감지

영속성 컨텍스트에서 보관되는 데이터에 변경이 일어났는지 확인하고, 변경이 일어났다면 JPA가 UPDATE 쿼리문을 날려줘서 별도로 UPDATE 쿼리를 작성할 필요가 없다.

1차 캐시에서 최초로 영속성 컨텍스트에 들어온 객체 상태인 스냅샷과 Entity 실제 값을 비교하여, 다르다면 쓰기 지연 SQL 저장소에 update 문이 추가되어 반영 후 commit 된다.

 

 

5. 지연 로딩

엔티티를 DB에서 가져올 때 연관된 객체를 즉시 조회하지 않고, 나중에 필요할 때 DB에서 가져오는 지연 로딩을 사용할 수 있게 된다.

(즉시로딩: 엔티티를 조회할 때 연관된 객체를 모두 DB에서 가져오는 것)

 

 

 

https://velog.io/@suk13574/JPA-%EC%98%81%EC%86%8D%EC%84%B1-%EC%BB%A8%ED%85%8D%EC%8A%A4%ED%8A%B8%EC%9D%98-%EC%A0%84%EB%B0%98%EC%A0%81%EC%9D%B8-%EC%9D%B4%ED%95%B4%EA%B0%9C%EB%85%90-%EC%9E%A5%EC%A0%90-%EB%8F%99%EC%9E%91-%EB%B0%A9