JPA 영속성 컨텍스트

test·2022년 1월 18일
0

JPA

목록 보기
4/5
post-thumbnail

영속성 컨텍스트의 이점

1차 캐시 조회

Member member = new Member();			// entity 생성(비영속 상태)
member.setId("member1");
member.setUsername("username1");
em.persist(member);				// entity 1차 캐시에 저장(영속 상태)
Member member1 = em.find(Member.class, "member1");// 1차 캐시에서 조회

데이터 베이스 조회

Member member2 = em.find(Member.class, "member2");

  • 엔티티 매니저는 데이터베이스 트랜잭션 단위로 생성, 트랜잭션이 끝날때 같이 종료.
    클라이언트 요청이 들어와서 하나의 비즈니스 로직이 끝나버리면 영속성 컨텍스트를 지울때 1차 캐시도 날아간다. 즉 그 짧은 순간에만 이득이 있다. 여러명의 사용자가 사용하는 캐시는 아니다.

동일성 보장

컬렉션 조회처럼 JPA가 영속 엔티티의 동일성을 보장(1차 캐시가 있어서 가능)

Member memberA = em.find(Member.class, "member1");
Member memberB = em.find(Member.class, "member1");
memberA == memberB; // true

쓰기 지연

em.persist(memberA);
em.persist(memberB); // 아직 insert query를 디비로 보내지 않음
transaction.commit(); // commit할 때 디비로 query 전송

트랜잭션을 커밋하면 커밋하는 시점에 쓰기 지연 SQL 저장소에 있던 쿼리들이 flush 되면서 날라간다. 그리고 실제 DB 트랜잭션이 커밋된다.

여기서 바로 버퍼링이라는 기능이 나온다.

만약 매번 엔티티 영속화할 때마다 DB에 쿼리날리게 되면 최적화할 수 있는 여지 자체가 없어진다.
사실 데이터베이스에 아무리 데이터 많이 집어넣어도 커밋 안하면 DB 반영이 안된다. 따라서 커밋하기 직전에만 INSERT 치면 된다.
커밋하기 직전에 위의 예시에서 보면 쓰기지연 SQL저장소에 쿼리들이 쌓여있가 이 쿼리들을 한번에 날릴 수 있다. 이걸 가능하게 해주는게 JDBC Batch 를 사용해서 가능하다.
Batch사용하면 굉장히 코드가 복잡해 지지만 Hibernate는 batch_size 옵션으로 적용 가능하다.

플러시

flush

flush란 영속성 컨텍스트의 변경내용을 데이터베이스에 반영하는 작업

  • 영속성 컨텍스트를 비우지 않는다.
  • 영속성 컨텍스트의 변경내용을 데이터베이스에 동기화
  • 트랜잭션이라는 작업 단위가 중요 -> 커밋 직전에만 동기화 하면 된다.

플러시 발생

  • 변경 감지
  • 수정된 entity 쓰기 지연 SQL 저장소에 등록
  • 쓰기 지연 SQL 저장소의 쿼리를 데이터베이스에 전송(등록, 수정, 삭제 쿼리)
  • 1차 캐시가 지워지지는 않는다.

플러시 하는 방법

  • em.flush() - 직접 호출
  • 트랜젝션 커밋 - flush 자동 호출
  • JPQL 쿼리 실행 - flush 자동 호출

준영속

준영속 상태

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

준영속 상태로 만드는 방법

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

참조 : 김영한님 JPA 강의

profile
bedev

0개의 댓글