영속성 컨텍스트...

Yangray·2021년 9월 27일
1

JPA

목록 보기
1/5

영속성 컨텍스트

  • 엔티티를 영구 저장하는 환경이라는 뜻

    클라이언트 요청이 들어오면 EntityManagerFactory에서 EntityManager를 생성하여
    DB커넥션풀을 사용하여 데이터를 CRUD한다.

  • 영속성 컨텍스트는 논리적인 개념이며, 눈에 보이지 않는다.

  • 엔티티 매니저를 통해 영속성 컨텍스트에 접근한다.

    엔티티의 생명주기

    비영속

  • 영속성 컨텍스트와 전혀 관계가 없는 새로운 상태

//객체를 생성한 상태(비영속)
Member member = new Member("memeber1","회원1");

영속

  • 영속성 컨텍스트에 관리되는 상태
//객체를 생성한 상태(비영속)
Member member = new Member("memeber1","회원1");

EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();

//객체를 저장한 상태(영속)
em.persist(member);

준영속

  • 영속성 컨텍스트에 저장되었다가 분리된 상태
//회원 엔티티를 영속성 컨텍스트에서 분리, 준영속 상태 
em.detach(member);

삭제

  • 영속성 컨텍스트에서 삭제된 상태
//객체를 삭제한 상태(삭제) 
em.remove(member);

영속성 컨텍스트의 이점

1차 캐시

영속성 컨텍스트에 엔티티를 영속 시키면 1차 캐시에 저장이된다.
그리고 조회시 1차 캐시에 존재하면 1차 캐시에서 바로 조회를 하고 1차 캐시에 존재하지 않는 경우 데이터베이스에서 조회 후 1차 캐시에 저장하고 리턴한다.

비즈니스가 종료가 되면 영속성컨텍스트는 비우게 된다.
성능상 이점은 거의 없다.

영속된 엔티티의 동일성(identity)보장

1차 캐시로 반복 가능한 읽기 등급의 트랜잭션 격리 수준을 데이터베이스가 아닌 애플리케이션 차원에서 제공한다.

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

//객체를 생성한 상태(비영속)
Member member1 = new Member("memeber1","회원1");
Member member2 = new Member("memeber2","회원2");

EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();

//객체를 저장한 상태(영속)
em.persist(member1);
em.persist(member2);
// INSERT SQL을 데이터베이스에 보내지 않는다

// 커밋하는 순간 데이터베이스에 INSERT SQL을 보낸다.
tx.commit();

em.persist(member1)를 하면 영속성 컨텍스트 1차 캐시에 저장이되고,
쓰기 지연 SQL 저장소에 INSERT query 생성 후 저장한다.
이어서 em.persist(member2)를 하면 영속성 컨텍스트 1차 캐시에 저장이되고,
쓰기 지연 SQL 저장소에 INSERT query 생성 후 저장한다.

tx.commit();을 하는 순간
영속성 컨텍스트에 저장되어 있던 INSERT query문들을 DB에 flush하여 commit하게된다.

이로인해 네트워크를 여러번 타지 않게 되어한번에 요청을 처리하게 된다. 따라서 부하를 줄일 수 있게된다.

엔티티 수정(변경감지 diry checking)

EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();

//영속 엔티티 조회
Member member1 = em.find(Member.class, "member1");

//영속 엔티티 데이터 수정
member1.setUsername("유저1");
member1.setId("userA");

tx.commit();

영속성 컨텍스트는 1차 캐시와 엔티티간 변경된 부분을 비교하고
UPDATE query를 생성하여 쓰기 지연 SQL 저장소에 저장하게 된다.
commit이 발생하면 db에 commit한다.

flush

영속성 컨텍스트의 변경내용을 데이터베이스에 반영!!

flush 발생

  • 변경감지
  • 수정된 엔티티 쓰기 지연 sql 저장소에 등록
  • 쓰기 지연 sql 저장소의 query를 db에 전송 (등록,수정,삭제..)

영속성 컨텍스트를 flush하는 법

  • em.flsuh() : 직접 호출
  • tx.commit() : 트랜젝션 커밋 시 플러시 자동 호출
  • JPQL : JPQL query 시 플러시 자동 호출

flush 모드 옵션

  • FlushModeType.AUTO : 커밋이나 쿼리를 실행할 때 플러시 (default)
  • FlushModeType.COMMIT : 커밋할 때만 플러시

flush는 영속성 컨텍스트를 비우는 것이 아니라 영속성컨텍스트의 변경 내용을 데이터베이스에
동기화 하는 메서드이다.

준영속(detached) 상태

  • 영속 -> 준영속
  • 영속 상태의 엔티티가 영속성 컨텍스트에서 분리(detached)된 상태
  • 영속성 컨텍스트가 제공하는 기능을 사용 불가능

영속 상태를 준영속 상태로 바꾸는 법

  • em.detach(entity) : 특정 엔티티만 준영속 상태로 전환
  • em.clear() : 영속성 컨텍스트를 완전히 초기화 시킴
  • em.close() : 영속성 컨텍스트를 종료 시킴

😀 정리

JPA에서 가장 중요한 개념 중 한가지인 영속성 컨텍스트
영속성 컨텍스트는 JPA를 이해하는데 가장 중요한 용어이다.
엔티티를 영구 저장하는 환경을 의미한다.
엔티티매니저 팩토리에서 요청이 들어오면 엔티티 매니저를 생성해 엔티티를 1차 캐시에 저장한다.엔티티 조회가 요청이 들어오면 우선 1차 캐시에서 조회 후 있으면 1차 캐시에 엔티티를 리턴한다.1차 캐시에 존재하지 않으면 데이터베이스에 접근해 조회 후 1차 캐시에 저장하고 리턴한다.
영속성 컨텍스트에는 생명주기가 있다.
1. 비영속 상태는 영속성 컨텍스트와 엔티티가 전혀 관련 없는 새로운 상태를 의미한다. 즉 단순히 new Member(); 하고 객체가 생성만 된 상태이다.
2. 영속 상태 객체가 생성이 되고 em.persist(entity)하여 엔티티 컨텍스트에 저장하여 엔티티 가 관리되어지는 상태이다.
3. 준영속 상태는 영속 상태였던 엔티티를 영속성 컨텍스트에서 분리된 상태를 말한다.
4. 삭제는 영속성 컨텍스트에서 삭제를 의미한다.
영속성 컨텍스트에 persist하게 되면 데이터베이스에 바로 반영이 되지 않고, 쓰기지연 sql에 insert나update 쿼리를 생성해 저장 후 트랜잭션 커밋이 실행되면 데이터베이스에 sql문을 실행하여 데이터를 등록 수정 삭제를 하게 된다.
트랙잭션 커밋은 JPQL쿼리를 실행하거나 트랜잭션을 커밋하면 자동으로 flush하여 실행이되고, 수동으로 em.flush를 하여 수동으로 플러시를 할 수 있다.
이러한 점으로 요청이 많으면 네트워크 부하를 줄이는 등 성능상 문제를 해결할 수 있게된다.
flush는 2가지 옵션이 있는데 기본으로 커밋이나 쿼리를 실행할 때 flush가 되는 것과 커밋 할 때만 flush되는 옵션 2가지가 존재한다.

profile
시작은 미약하나 그 끝은 창대하리라

0개의 댓글