[JPA] 영속성 컨텍스트📘

Umji You·2021년 10월 20일
0

JPA기본

목록 보기
2/6

영속성 관리

  • JPA에서 가장 중요한 2가지
    • 객체와 DB 매핑(ORM - Object Relational Mapping)
    • 영속성 컨텍스트 - JPA 내부 동작

EntityManagerFactory와 EntityManager

image

  • EntityManagerFactory

    • Application loading 시점에 DB당 딱 하나만 생성하여 사용한다.
    • 여러 스레드에서 동시에 접근해도 안전하지만, 상당한 비용이 든다.
    • WAS가 종료되는 시점에 EntityManagerFactory.close();로 닫아준다.
      • 그래야 내부적으로 Connection Pooling에 대한 자원이 반납된다.
  • EntityManager

    • 사용자의 요청이 있을때 사용하고 반납해준다.(Threan safe하지 않음!)
    • Transactional단위로 실행된다.
    • EntityManager.close()를 해주어야 내부적으로 DB연결을 반환한다.
      • Transactional처리 후 닫아준다.
  • Transactional

    • Data에 변경, 생성 작업은 반드시 여기 안에서 이루어져야만 한다.
    EntityManager em = EntityManagerFactory.createEntityManager();
    
    EntityTransaction transaction = em.getTransaction();

    transaction.begin();
    transaction.commmit();
    transaction.rollback();
  • EntityManager와 영속성 컨텍스트 관계
    image
  • EntityManager가 생성되면 영속성 컨텍스트와 1:1로 생성된다.



영속성 컨텍스트란?

image

  • Entity를 영구 저장하는 곳
    • 영속성 컨텍스트ApplicationDB사이에서 객체를 보관하는 논리적 개념이다.
  • EntityManager룰 통해 영속성 컨텍스트에에 접근할 수 있다.



Entity 생명주기

image

  • 비영속(new/transient)
    • 영속성 컨텍스트에 없는 상태
      • Entity가 관리되어지지 않는 상태를 의미한다.
  • 영속(managed)
    • 영속성 컨텍스트에 저장된 상태
      • Entity가 관리되어지는 상태
      • DB에 저장된 상태는 아니다!
    entityManager.persist(Entity);
  • 준영속(detached)
    • 영속성 컨텍스트에서 분리된 상태
      • 더이상 관리하지 않는다.
      • 개발자가 직접 준영속을 만들 일은 거의 없다.
    entityManager.detach(Entity);
  • 삭제(removed)
    • 실제 DB에서 삭제된 상태를 의미한다.
    entityManager.remove(Entity);

영속성 컨텍스트의 이점

1. 1차 캐시

image

    // 영속성 컨텍스트 1차 캐시에 저장된다.
    entityManager.persist(Entity);

    //1차 캐시에서 조회한다.
    Object find = entityManager.find(Object.class, Entity.getId);
  • 만약 1차 캐시에서 찾지 못할 경우 DB에서 Entity를 가져와 영속성 컨텍스트에 저장(1차 캐시 저장)후 값을 가져온다.
    • 1차 캐시 같은 경우 요청이 종료되면 영속성 컨텍스트를 지우면서 삭제된다.

2. 동일성 보장(identify)

    //1차 캐시에서 조회한다.
    Object find = entityManager.find(Object.class, 1L);
    Object find2 = entityManager.find(Object.class, 1L);    
  • 영속성 컨텍스트에서 관리되는 1차캐시에서 존재하는 값을 가져오기 때문에 언제나 같은 값을 보장한다.
  • 1차 캐시로 반복 가능한 읽기(REPEATABLE READ) 등급의 트랜잭
    션 격리 수준을 데이터베이스가 아닌 애플리케이션 차원에서 제공

3. 트랜잭션을 지원하는 쓰기 지연(Transaction Write-behind)

EntityManager em = emf.createEntityManager();
EntityTransaction transaction = em.getTransaction();
//엔티티 매니저는 데이터 변경시 트랜잭션을 시작해야 한다.
transaction.begin(); // [트랜잭션] 시작
em.persist(memberA);
em.persist(memberB);
//여기까지 INSERT SQL을 데이터베이스에 보내지 않는다.
transaction.commit(); // [트랜잭션] 커밋
  • .commit하는 순간 데이터베이스에 INSERT SQL을 보낸다.

4. 변경 감지 (Dirty Checking)

image

 transaction.begin(); // [트랜잭션] 시작
// 영속 엔티티 조회
Member memberA = em.find(Member.class, "memberA");
// 영속 엔티티 데이터 수정
memberA.setUsername("hi");
memberA.setAge(10);
//em.update(member) 이런 코드가 있어야 하지 않을까?
transaction.commit(); 



플러시란?

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

플러시가 발생하면?

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

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

  • entityManager.flush()
  • transaction.commit()
  • JPQL 쿼리 실행

주의사항 : flush()한다고 영속성 컨텍스트가 비워지지 않는다. 단지 DB에 동기화를 시킬 뿐이다.


🔎참고

[Inflearn]김영한 - 자바 ORM표준 JPA 기본편

profile
꾸준한 기록을 하자

0개의 댓글