2. JPA 영속성 관리

1. 영속성 컨텍스트

1) 비영속 VS 영속

// 비영속
Member member = new Member();
member.setId(100L);
member.setName("HelloJpa");

//영속
System.out.println("====Before====");
em.persist(member);
System.out.println("====After====");

>> 실행 결과
>> Before
>> After
>> insert ~~~
  • 영속 상태가 된다고 해서 바로 쿼리가 실행되지 않는다.
  • 트랜잭션 커밋을 해야 쿼리가 날아간다.

2) 준영속

  • em.detach() 사용 시 영속성 제거

3) 영속성 컨텍스트의 이점

  • 1차 캐시

    • 이전에 찾아온 객체를 다시 조회하지 않고 캐시에 임시 저장해 놓는다.
    • 고객의 요청이 종료되면 1차 캐시가 날라가서 그렇게 큰 쓸모는 없다.
  • 동일성 보장

    Member member1 = em.find(Member.class, 100L);
    Member member2 = em.find(Member.class, 100L);
    
    System.out.println("result = " + (member2 == member1)); 

    -> True라고 출력된다.

  • 엔티티를 등록할 때 트랜잭션을 지원하는 쓰기 지원(지연 로딩)

    • persist한다고 바로 쿼리문이 날라가지 않고 1차 캐시에 쌓아놓고 있다가 트랜잭션 커밋시에 쿼리 실행
    • property name="hibernate.jdbc.batch_size" value="10" 설정을 통해 배치 사이즈를 설정할 수 있다.
  • 엔티티 수정

    Member member = em.find(Member.class, 150l);
    member.setName("ZZZZ");
    

    -> em.persist(member)를 써줄 필요가 없음!!
    -> 알아서 변경을 감지해서 update 쿼리 실행

  • 엔티티 삭제

    • em.remove(memberId) 실행

2. 플러시

  • 플러시: 영속성 컨텍스트의 변경 내용을 데이터베이스에 반영
  • 플러시가 발생
    • 변경 감지
    • 수정된 엔티티 쓰기 지연 sql 저장소에 등록
    • 쓰기 지연 sql 저장소의 쿼리를 데이터베이스에 전송
  • 플러시 실행
    • em.flush()
    • 트랜잭션 커밋 호출
    • JPQL 쿼리 실행
  • 플러시를 해도 1차 캐시가 지워지지 않는다.
  • 플러시 모드 옵션
    • FlushModeType.Auto
      • 쿼리를 실행할 때만 플러시
    • FlushModeType.Commit
      • 커밋만 실행
      • JPQL에서 자동 플러시를 피할 때 사용

3. 준영속 상태

  • 영속 상태의 엔티티가 영속성 컨텍스트에서 분리(detached)
  • 영속성을 가지는 경우
    • em.persist()
    • em.find()를 실행했는데 1차 캐시에 값이 없을 경우
  • 준영속 상태로 만드는 방법
    • em.detached(): 특정 엔티티만 준영속 상태로 전환
    • em.clear(): 영속성 컨텍스트 통채로 지움
    • em.close(): 영속성 컨텍스트를 종료

좋은 웹페이지 즐겨찾기