[JPA] 02. JPA 내부 구조

joheera·2023년 7월 3일
0

JPA

목록 보기
2/9

영속성 컨텍스트

영속성 컨텍스트는 엔티티를 영구 저장하는 환경이라는 뜻이다. 영속성 컨텍스트는 논리적인 개념이며, EntityManager를 통해서 영속성 컨텍스트에 접근할 수 있다. J2SE 환경에서는 EntityManager와 영속성 컨텍스트가 1대1 관계이다.

Entity의 생명주기

transient/new(비영속)

영속성 컨텍스트와 전혀 관계가 없는 새로운 상태
ex) 객체를 생성하기만 한 상태

managed(영속)

영속성 컨텍스트에 관리되는 상태
ex) 생성한 객체를 em.persist()로 저장한 상태 -> DB에 저장된 것은 아니다.
em.find()로 영속성 컨텍스트에서 객체를 가져온 상태

detached(준영속)

영속성 컨텍스트에 저장되었다가 분리된 상태

removed(삭제)

삭제된 상태

// 비영속
Member member = new Member();
member.setId(100L);
member.setUsername("회원1");

// 영속
em.persist(member);

// 준영속
em.detach(member);

// 삭제
em.remove(member);

영속성 컨텍스트의 이점

1차 캐시에서 조회

JPA에서 객체를 조회할 때는 바로 DB를 조회하는 것이 아니라 1차 캐시에 해당 객체가 있는지부터 확인한다. 만약 1차 캐시에 객체가 있다면 1차 캐시에서 바로 값을 가져온다. 1차 캐시에 찾고자 하는 객체가 없다면, DB에서 값을 가져와 1차 캐시에 저장 후 값을 반환한다. 이후에 다시 해당 객체를 조회한다면 DB를 조회하지 않고 1차 캐시에 저장된 객체를 가져온다. 트랜잭션이 종료될 때 1차 캐시도 함께 지워지기 때문에 큰 성능 차이가 있지는 않다.

영속 엔티티의 동일성 보장

같은 트랜잭션 안에서 같은 객체를 조회할 경우 동일성을 보장한다. 1차 캐시로 반복 가능한 읽기(REPEATABLE READ)등급의 트랜잭션 격리 수준을 데이터베이스가 아닌 애플리케이션 차원에서 제공한다.

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

jpa는 em.persist(entity)를 실행할 때 INSERT SQL을 바로 데이터베이스에 보내지 않고, transaction을 commit하는 순간 데이터베이스에 INSERT SQL을 보낸다. em.persist(entity)를 실행하면 객체를 1차 캐시에 저장하고, INSERT SQL을 생성해 쓰기 지연 SQL 저장소에 저장해둔다. 이후 transaction을 commit할 때 쓰기 지연 SQL 저장소에 있던 SQL문들을 데이터베이스에 보낸다. SQL문을 바로 데이터베이스에 보내는 것이 아니라 모아서 한번에 보내는 버퍼링을 할 수 있기 때문에 성능적으로 이점이 있다.

변경 감지

jpa에서는 update 명령을 따로 호출할 필요가 없다. transaction을 commit하면 현재 entity와 처음 상태의 entity가 저장된 snapshot을 비교한다. entity에 변화가 있을 경우 UPDATE SQL을 생성하여 쓰기 지연 SQL 저장소에 저장하고, 데이터베이스에 SQL문들을 보낸다.

플러시

플러시는 영속성 컨텍스트의 변경 내용을 데이터베이스에 반영하는 것이다. 플러시가 발생하면 다음과 같은 일을 한다.

  • 변경 감지
  • 수정된 엔티티 쓰기 지연 SQL 저장소에 등록
  • 쓰기 지연 SQL 저장소의 쿼리를 데이터베이스에 전송

플러시는 영속성 컨텍스트를 비우는 것이 아니라 영속성 컨텍스트의 변경내용을 데이터베이스에 동기화 하는 것이다. transaction이라는 작업 단위가 중요하며, commit 직전에만 동기화를 하면 된다.

영속성 컨텍스트를 플러시하는 방법

  • em.flush() 을 사용하여 플러시를 직접 호출한다.
  • transaction을 commit 할 때 플러시가 자동 호출된다.
  • JPQL 쿼리가 실행 될 때 플러시가 자동 호출된다.

준영속 상태

준영속 상태란 영속 상태의 엔티티가 영속성 컨텍스트에서 분리된 것을 말한다. 준영속 상태에서는 영속성 컨텍스트가 제공하는 기능을 사용하지 못한다.

준영속 상태로 만드는 방법

  • em.detach(entity) 특정 entity만 준영속 상태로 전환한다.
  • em.clear() 영속성 컨텍스트를 모두 초기화한다.
  • em.close() 영속성 컨텍스트를 종료한다.

0개의 댓글