영속성 컨텍스트 이해하기

MinSeong Kang·2022년 8월 5일
0

spring

목록 보기
15/18

영속성 컨텍스트?? JPA를 공부하면서 가장 많이 듣는 단어이다. 또한 JPA에서 ORM(객체와 RDB와 매핑)하는 것과 동시에 매우 중요한 개념이다. 따라서 영속성 컨텍스트에 대해서 공부하고 포스팅하려 한다.

영속성 컨텍스트란?

  • 엔티티를 영구 저장하는 환경
  • 애플리케이션과 데이터베이스 사이에서 객체를 보관하는 논리적 개념
  • EntityManager를 통해 객체를 영속성 컨텍스트에 저장할 수 있다.

영속성 컨텍스트 생명주기

  • 비영속 : 영속성 컨텍스트와 관계 없는 새로운 상태
User user = new User("user1");
  • 영속 : 영속성 컨텍스트에 관리되는 상태
User user = new User("user1");
EntityManager em = entityManagerFactory.createEntityManager();
em.getTransaction().begin();
em.persist(user);
  • 준영속 : 영속성 컨텍스트에서 관리하는 상태였다가 분리된 상태
User user = new User("user1");
EntityManager em = entityManagerFactory.createEntityManager();
em.getTransaction().begin();
em.persist(user);
em.detach(user);
  • 삭제 : 실제 데이터 베이스에서 삭제된 상태
User user = new User("user1");
EntityManager em = entityManagerFactory.createEntityManager();
em.getTransaction().begin();
em.remove(user);

영속성 컨텍스트의 이점

1. 1차 캐시

  • 영속성 컨텍스트는 애플리케이션과 데이터베이스 사이에 존재한다. 이는 둘 사이의 캐시 역할을 할 수 있고 이는 1차 캐시라고 한다. 1차 캐시 즉 영속성 컨텍스트에 없는 경우 데이터베이스에서 직접 조회하고 영속성 컨텍스트에 저장한다. 만일 영속성 컨텍스트 내에 있는 데이터를 조회한다면, 직접 데이터베이스에 접근하지 않고 데이터를 조회할 수 있다.
  • 사실 이는 눈에 띄이는 성능 향상은 안되지만, 수많은 조회 요청이 있는 비즈니스 로직일 경우 성능 차이를 느낄 수 있을 것이다.
  • 영속성 컨텍스트는 애플리케이션에서 공유하지 않는다. 공유하는 캐시는 2차 캐시라고 한다.
em.persist(user); // 영속성 컨텍스트(1차 캐시)에 저장
User findUser = em.find(User.class, 1L); // DB 접근없이 1차 캐시에서 조회

2. 동일성 보장

  • User findUser = em.find(User.class, 1L); 등을 반복적으로 호출하면 영속성 컨텍스트에 있는 같은 인스턴스를 반환한다. 따라서 동일성 즉 == 을 보장한다.
em.persist(user); // 영속성 컨텍스트(1차 캐시)에 저장
User findUser1 = em.find(User.class, 1L); // DB 접근없이 1차 캐시에서 조회
User findUser2 = em.find(User.class, 1L); // DB 접근없이 1차 캐시에서 조회

findUser1 == findUser2 // true

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

  • 한 트랜잭션 내에서 수행되는 등록,삭제,변경 쿼리는 영속성 컨텍스트 내 쓰기 지연 SQL 저장소에 쌓인다. 이후 트랜잭션이 커밋될 때 데이터베이스에 해당 쿼리를 보낼 수 있다.

4. 변경 감지

  • 실제 em.update이란 메서드는 존재하지 않는다. JPA 자체가 실제 자바 컬렉션에서 데이터를 조회하고 변경하는 것과 같이 유사하게 만들어졌기 때문에, 영속성 컨텍스트에 존재하는 데이터를 수정하기 위해 데이터를 조회해 setter 메서드로 변경하면 된다.
  • 이를 변경 감지(더티 체킹)이라고 한다. 영속성 컨텍스트에서는 데이터 최초 조회시 해당 데이터의 스냅샷을 저장한다. 데이터 값과 최초 스냅샷을 비교하여 데이터가 변경되었다면, UPDATE 쿼리를 쓰기 지연 SQL 저장소에 저장하고 커밋 시점에 데이터베이스에 적용된다.
em.persist(user); // 영속성 컨텍스트(1차 캐시)에 저장
User findUser1 = em.find(User.class, 1L); // DB 접근없이 1차 캐시에서 조회
findUser1.setName("user2"); // 영속 엔티티 수정

commit! // 커밋시 쓰기 지연 SQL 저장소의 쿼리문 실행

5. 지연 로딩


참고자료

<https://www.inflearn.com/course/ORM-JPA-Basic/dashboard>

0개의 댓글