https://www.inflearn.com/course/ORM-JPA-Basic/dashboard
Inflearn의 김영한 강사님 강의 [자바 ORM 표준 JPA 프로그래밍 - 기본편] 을 보고 정리했습니다.
영속성 컨텍스트
실제 JPA가 내부에서 어떻게 동작하는지? 와 관련된 부분
엔티티 매니저 팩토리와 엔티티 매니저
사용자의 요청이 들어올 경우
- 엔티티 매니저 팩토리 : 엔티티 매니저를 생성한다.
- 엔티티 매니저 : 내부적으로 DB 커넥션을 사용하여 DB를 사용한다.
영속성 컨텍스트
- "엔티티를 영구 저장하는 환경"
EntityManager.persist(entity)
- 엔티티 매니저를 통해
entity
를 영속성 컨텍스트 에 접근한다.
생명 주기
- 비영속 : 새로운 상태, 영속성 컨텍스트와 관계가 없다.
- 객체를 생성만 한 상태. JPA와 관계없는 상태.
- 영속 : 영속성 컨텍스트에 관리되는 상태
- 영속성 컨텍스트안에 객체가 들어간 상태.
em.persist(entity)
em
은 엔티티 매니저 팩토리를 통해 만든 엔티티 매니저.
- 아직 DB에 저장된 상태는 아니다. -> 트랜잭션을 커밋해야 DB에 저장됨
- 준영속 : 영속성 컨텍스트에서 분리된 상태
- 삭제
영속성 컨텍스트의 이점
App과 DB 사이에 중간계층의 느낌.
- 1차 캐시
- 조회할 때 : 1차 캐시에서 조회가능하다. == 빠르다.
em.find(entity.class, "entityPK")
- 1차 캐시에 없을 때 : DB조회 > 1차 캐시에 저장 > 반환
- 엔티티 매니저는 보통 데이터 트랜잭션단위로 만들고 끝날때 없애기 때문에, 사실 큰 효율은 기대하기 힘들다.
- 동일성 보장
==
비교를 보장해준다. (자바 Collection에서 같은 레퍼런스의 값을 비교할 때 처럼)
- 같은 트랜잭션 안에서 비교해야한다.
- 트랜잭션을 지원하는 쓰기지연
- 엔티티 매니저는 데이터 변경시 트랜잭션을 시작해야 한다.
em.persist(entity)
시점에는 INSERT SQL을 DB에 보내지 않는다.
- 1차 캐시에 저장된다.
- 쓰기 지연 SQL 저장소에 INSERT SQL을 저장한다.
transaction.commit()
시점에 INSERT SQL을 DB에 보낸다.
- 쓰기 지연 SQL 저장소에 있는 INSERT SQL을 일괄 실행한다.
- JDBC Batch : 버퍼링 기능, 모았다가 DB에 한번에 넣는다.
hibernate.jdbc.batch_size
설정
- 단순한 옵션 하나로 성능의 이점을 가질 수 있다.
- 변경 감지
entity.setName('"ABCD"')
등으로 객체의 값을 변경할 경우, JPA가 알아서 수정해서 DB에 update한다.
- 트랜잭션을
commit
하는 시점에 flush()
가 호출된다.
- 엔티티와 1차캐시의 스냅샷과 비교한다.
- 변경된 내용이 있으면 UPDATE SQL을 생성하여 쓰기 지연 SQL 저장소에 넣는다.
- DB에 반영한다.
em.remove()
도 동일한 메커니즘
- 지연로딩
플러시
영속성 컨텍스트의 변경내용을 DB에 반영
- 변경감지 > 수정된 엔티티 쓰기 지연 SQL 저장소에 등록 > 쓰기 지연 SQL 저장소의 쿼리를 DB에 전송(등록, 수정, 삭제)
- 사용방법
em.flush()
: 직접호출, 사용할 일이 많지 않다.
- 트랜잭션 커밋
- JPQL 쿼리 실행
- 1차 캐시의 내용이 지워지지 않는다, 변경된 내용이 DB에 반영이 되는 과정
준영속 상태
영속성 컨텍스트에서 분리된 상태, 영속성 컨텍스트의 기능을 사용하지 못한다.
em.detach(entity)
: 특정 엔티티만 준영속 상태로 전환
em.clear()
: 영속성 컨텍스트를 초기화
em.close()
: 영속성 컨텍스트를 종료