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

개발자·2021년 12월 27일
0

JPA

목록 보기
2/10
post-thumbnail

영속성 컨텍스트

엔티티를 영구 저장하는 환경

EntityManager.persist(entity); // EntityManager를 통해 영속성 컨텍스트에 접근

엔티티의 생명주기

  • 비영속 : 영속성 컨텍스트와 전혀 관계가 없는 새로운 상태
  • 영속 : 영속성 컨텍스트에 관리되는 상태
  • 준영속 : 영속성 컨텍스트에 저장되었다가 분리된 상태
  • 삭제 : 삭제된 상태

비영속/영속

// 객체를 생성한 상태(비영속)
Member member = new Member();
member.setId(101L);

EntityManager em = emf.createEntityManager();
em.getTransaction().begin();

// 객체를 저장한 상태(영속) -> 1차 캐시에 저장
em.persist(member);

// 1차 캐시에서 조회(없으면 DB에서 조회)
Member findMember = em.find(Member.class, 101L);

영속 엔티티의 동일성 보장

Member findMember1 = em.find(Member.class, 101L);
Member findMember2 = em.find(Member.class, 101L);

System.out.println("result = " + (findMember1 == findMember2));

엔티티 등록(트랜잭션을 지원하는 쓰기 지연)

SQL을 모아서 저장해뒀다 커밋 시점에 한번에 실행

Member member1 = new Member(150L, "A");
Member member2 = new Member(160L, "B");

em.persist(member1);
em.persist(member2);

tx.commit(); // 커밋하는 순간에 쿼리 실행

엔티티 수정(변경 감지)

커밋 시점에 flush()가 실행되고 엔티티와 스냅샷(최초시점)을 비교해 변경사항이 감지되면 UPDATE 쿼리 실행

Member findMember = em.find(Member.class, 101L);
member.setName("ZZZ");

tx.commit();

flush

  • 영속성 컨텍스트를 비우지 않음
  • 영속성 컨텍스트의 변경내용을 데이터베이스에 동기화
  • 트랜잭션이라는 작업 단위가 중요 -> 커밋 직전에만 동기화하면 됨
  • 수정된 엔티티를 쓰기 지연 SQL 저장소에 등록
  • 쓰기 지연 SQL 저장소의 쿼리를 데이터베이스에 전송(등록, 수정, 삭제 쿼리)

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

  • em.flush() : 직접 호출
Member member = new Member(200L, "member200");
em.persist(member);

em.flush(); // 쿼리 즉시 실행
tx.commit();
  • 트랜잭션 커밋 // 플러시 자동 호출
  • JPQL 쿼리 실행 // 플러시 자동 호출

준영속 상태

  • 영속 상태의 엔티티가 영속성 컨텍스트에서 분리
  • 영속성 컨텍스트가 제공하는 기능을 사용 못함

준영속 상태로 만드는 방법

  • em.detach(entity) : 특정 엔티티만 준영속 상태로 전환
  • em.clear() : 영속성 컨텍스트를 완전히 초기화
  • em.close() : 영속성 컨텍스트를 종료
Member member = em.find(Member.class, 150L);
member.setName("AAAA");

em.detach(member); // 영속성 컨텍스트에서 분리
tx.commit(); // update 쿼리가 실행되지 않음!!

Ref.

[인프런] 자바 ORM 표준 JPA 프로그래밍 - 기본편 (김영한)

profile
log.info("공부 기록 블로9")

0개의 댓글