쟈미로그

[JPA] 영속성 관리 - 2 본문

JPA

[JPA] 영속성 관리 - 2

쟈미 2023. 5. 30. 00:39

영속성 컨텍스트의 특징/장점

  1. 1차 캐시
  2. 동일성 보장
  3. 트랜잭션을 지원하는 쓰기 지연
  4. 변경 감지
  5. 지연 로딩

영속성 컨텍스트가 필요한 이유와 장점을 예시와 함께 알아보자.

 

 

1. 1차 캐시

영속성 컨텍스트 내부의 캐시. 영속 상태의 엔티티들이 저장되는 곳이라고 보면 된다.

쉽게 말하면, @Id로 매핑한 키-엔티티 인스턴스가 Map으로 저장되는 장소다.

 

em.persist(~~); 를 통해 엔티티를 영속하면 아래 같은 그림이 된다.

 

엔티티 조회

조회를 위해서 em.find()를 호출하면 1차 캐시에서 엔티티를 우선으로 찾고, 캐시에 없으면 DB에서 조회를 한다.

(메모리에 있는 1차 캐시에서 바로 조회할 수 있으므로 성능상 장점이 생김)

 

캐시에 없어서 DB에서 조회를 한 경우엔, 조회한 엔티티를 1차 캐시에 우선 저장한 후에 영속 상태가 된 엔티티를 반환한다!

 

 

2. 동일성 보장

1차 캐시에서 em.find()로 같은 엔티티를 조회하면 항상 동일한 인스턴스가 반환된다. 즉, 동일성이 보장된다.

Member a = em.find(Member.class, 1);
Member b = em.find(Member.class, 1);

System.out.println(a == b);

위 코드를 실행해보면 true가 반환된다는 뜻!

 

 

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

엔티티 매니저는 트랜잭션이 커밋되기 직전까지 INSERT 쿼리를 DB에 바로 쏘지 않고 내부 쿼리 저장소에 쌓는다. 그리고 트랜잭션이 커밋될 때 모아둔 쿼리를 DB에 모두 보내게 되는데, 이걸 트랜잭션을 지원하는 쓰기 지연이라 한다.

 

이를 통해 얻는 장점이 뭐냐면, save() 메소드가 호출될 때마다 매번 DB에 등록 쿼리를 날리는 것이 아니라, 쿼리를 모아뒀다가 트랜잭션 커밋 시에 모든 쿼리를 DB에 보내버려도 같은 결과가 나온다는 것이다.

(이 기능을 잘 활용하면 성능 최적화가 가능하다고 하는데, 이건 책 15.4.5절에서 추가로 나온다고 함)

 

 

4. 변경 감지 (dirty checking)

SQL에선 수정 쿼리 작성 시 컬럼을 일일히 작성해야한다.

이 방식은 실수가 발생하기 쉽고, 수정 쿼리와 비즈니스 로직이 밀접하게 연관이 된다는 문제를 야기한다.

 

하지만 JPA는 엔티티 수정을 변경 감지를 통해 지원해서 위와 같은 문제를 해결한다. JPA는 따로 em.update 같은 메소드가 없고, 영속 상태의 인스턴스를 수정하면 DB에 반영된다.

변경 감지 과정을 알아보자.

  1. JPA는 엔티티가 영속화될 때, 최초 상태를 복사해서 스냅샷으로 저장해둔다.
  2. 그리고 flush 시점에 스냅샷과 엔티티 인스턴스를 비교해서 변경이 일어난 엔티티를 찾는다.
  3. 변경된 엔티티는 UPDATE 쿼리를 생성해서 쓰기 지연 SQL 저장소에 보낸다.
  4. 이 SQL를 DB에 보낸다.
  5. 트랜잭션을 커밋한다.

과정에서 알 수 있듯 변경 감지는 영속 상태의 엔티티에만 적용된다!

 

 

Comments