[자바 ORM 표준 JPA 프로그래밍] 3. 영속성 관리 - 내부 동작 방식

서요이·2022년 10월 3일
0
post-thumbnail

3. 영속성 관리 - 내부 동작 방식

영속성 컨텍스트 1

JPA에서 가장 중요한 2가지

  • 객체와 관계형 데이터베이스 매핑
  • 영속성 컨텍스트

영속성 컨텍스트

  • JPA를 이해하는데 가장 중요한 용어
  • 엔티티를 영구 저장하는 환경
  • EntityManager.persist(entity); → 엔티티를 DB에 저장하는 것이 아니라 영속성 컨텍스트에 저장
  • 엔티티 매니저와 영속성 컨텍스트 1:1

영속성 컨텍스트 2

엔티티의 생명주기

  • 비영속 (new/transient)
    // 객체를 생성한 상태(비영속)
    Member member = new Member();
    member.setId("memver1");
    member.setUsername("회원1");
  • 영속 (managed)
    EntityManager em = emf.createEntityManager();
    em.getTransaction().begin();
    // 객체를 저장한 상태(영속)
    em.persist(member);
  • 준영속 (detached)
    // 회원 엔티티를 영속성 컨텍스트에서 분리, 준영속 상태
    em.detach(member);
  • 삭제 (removed)
    // 객체를 삭제한 상태(삭제)
    em.remove(member);

영속성 컨텍스트의 이점

  • 1차 캐시
    // 엔티티를 생성한 상태
    Member member = new Member();
    member.setId("member1");
    member.setUsername("회원1");
    
    // 1차 캐시에 저장됨
    em.persist(member);
    
    // 1차 캐시에서 조회
    Member findMember = em.find(Member.class, "member1");
    
    // 데이터베이스에서 조회
    Member findMember2 = em.find(Member.class, "member2");
  • 동일성(identity) 보장
    Member a = em.find(Member.class, "member1");
    Member b = em.find(Member.class, "member1");
    
    System.out.println(a == b); //동일성 비교 true
  • 트랜잭션을 지원하는 쓰기 지연(transactional write-behind)
    EntityManager em = emf.createEntityManager();
    EntityTransaction transaction = em.getTransaction();
    //엔티티 매니저는 데이터 변경시 트랜잭션을 시작해야 한다.
    transaction.begin(); // [트랜잭션] 시작
    
    em.persist(memberA);
    em.persist(memberB);
    //여기까지 INSERT SQL을 데이터베이스에 보내지 않는다.
    
    //커밋하는 순간 데이터베이스에 INSERT SQL을 보낸다.
    transaction.commit(); // [트랜잭션] 커밋
  • 변경 감지(Dirty Checking)
    영속성 컨텍스트에 들어왔을 때의 상태를 스냅샷
    커밋되는 시점에 엔티티와 스냅샷 비교해서 Update SQL 생성
     EntityManager em = emf.createEntityManager();
     EntityTransaction transaction = em.getTransaction();
     transaction.begin(); // [트랜잭션] 시작
    
     // 영속 엔티티 조회
     Member memberA = em.find(Member.class, "memberA");
    
     // 영속 엔티티 데이터 수정
     memberA.setUsername("hi");
     memberA.setAge(10);
    
     //em.update(member) 이런 코드가 있어야 하지 않을까?
    
     transaction.commit(); // [트랜잭션] 커밋

플러시

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

플러시 발생

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

준영속 상태

영속 → 준영속
영속 상태의 엔티티가 영속성 컨텍스트에서 분리(detached)
영속성 컨텍스트 제공 기능 사용 불가
JPA에서 관리하지 않음

// 영속
Member member = em.find(Member.class, 150L);
member.setName("AAAAA");

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

트랜잭션 커밋해도 아무 일도 일어나지 않음

준영속 상태로 만드는 방법

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

0개의 댓글