영속성 컨텍스트의 이점
영속성 컨텍스트가 엔티티를 관리하는 것은 다음과 같은 이점이 있다.
- 1차 캐시
- 동일성 보장
- 트랜잭션을 지원하는 쓰기 지연
- 변경 감지
- 지연 로딩
1차 캐시
영속성 컨텍스트는 내부에 캐시를 가지고 있는데 이를 1차 캐시
라 하고 영속성 컨텍스트가 관리하는 엔티티들은 모두 이곳에 저장된다.
em.persist(member)
를 통해 영속성 컨텍스트의1차 캐시
에 엔티티 저장- 영속성 컨텍스트 내부에
@Id로 매핑한 식별자
를 키로 가지고엔티티 인스턴스
를 값으로 가지는 Map이 존재
엔티티 조회 - 1차 캐시에서 조회
em.find()
를 통해 엔티티를 조회 시 JPA는 우선 1차 캐시
에서 식별자 값으로 엔티티를 찾는다. 만약 찾고자 하는 엔티티가 있으면 데이터베이스를 조회하지 않고 메모리에 있는 1차 캐시
에서 엔티티를 조회하여 반환한다.
1차 캐시
조회1차 캐시
에서 엔티티 반환 (1차 캐시에 엔티티가 있을 시)
엔티티 조회 - 데이터 베이스에서 조회
만약 엔티티가 1차 캐시
에 없으면 엔티티 매니저는 데이터 베이스에서 값을 조회한다. 그리고 조회된 값을 통해 엔티티를 생성하고 이를 1차 캐시
에 저장한 후 영속 상태
의 엔티티를 반환한다.
1차 캐시
조회- 데이터 베이스 조회 (1차 캐시에 엔티티가 없을 시)
1차 캐시
에 엔티티 저장- 엔티티 반환 (영속 상태)
동일성 보장
JPA는 영속성 컨텍스트가 관리하는 영속 상태의 엔티티에 대해서 동일성을 보장해 준다. 이는 영속성 컨텍스트 내부의 1차 캐시가 엔티티를 Map으로 캐싱하고 있기 때문에 같은 식별자(@Id)에 대해서 항상 같은 인스턴스에 접근하게 되므로 동일성이 보장된다.
트랜잭션을 지원하는 쓰기 지연
엔티티 매니저는 트랜잭션을 커밋하기 직전까지 데이터베이스의 엔티티를 저장하지 않는다.(트랜잭션 커밋직전까지 Insert Query를 보내지 않는다.)
em.persist()
를 통해 엔티티를 1차 캐시
에 저장하고 Insert Query
를 생성하여 쓰기지연 SQL 저장소
에 저장한다. 트랜잭션이 커밋되는 시점에 쓰기지연 SQL 저장소
의 모인 쿼리들을 데이터베이스에 보낸다. 마지막으로 실제 데이터베이스 트랜잭션이 커밋된다.
1차 캐시
에 엔티티 저장Insert Query
생성 후쓰기지연 SQL 저장소
에 쿼리 저장- 트랜잭션 커밋 시
쓰기지연 SQL 저장소
에 저장된 쿼리들을 데이터베이스로 전송 - 데이터베이스 트랜잭션 커밋
변경감지
JPA에서는 변경감지(dirty checking)
기능을 제공하고 이를 통해 엔티티의 값을 변경할 수 있다.
1
2
3
4
5
6
7
8
9
10
11
12
EntityManager em = emf.createEntityManager();
EntityTransaction transaction = em.getTransaction();
transaction.begin() // 트랜잭션 시작
// 영속 엔티티 조회
Member memberA = em.find(Member.class, "memberA");
// 영속 엔티티 데이터 수정
memberA.setUsername("hi");
memberA.setAge(10);
transaction.commit(); // 트랜잭션 커밋
변경감지(dirty checking)
는 위의 코드와 같이 영속상태의 엔티티를 조회 후 setter
를 통해 값을 변경하면 트랜잭션이 커밋될 때 변경사항을 데이터 베이스에 자동으로 반영하는 기능이다.
JPA 영속성 컨텍스트 내부에 엔티티의 최초 상태를 복사하여 저장해두는데 이를 스냅샷이라 한다. 트랜잭션이 커밋되면 스냅샷과 엔티티의 값을 비교하여 데이터 베이스에 변경사항을 반영한다.
Comments powered by Disqus.