JPA에서 가장 중요한 개념
1. 영속성 컨텍스트 - 실제 JPA 동작과 관련
2. 객체와 관계형 데이터 베이스 매핑(ORM) - 설계과 관련
Entity를 영구 저장하는 환경이라는 뜻
EntityManager를 통해 영속성 컨텍스트에 접근하고 관리
EntityManager를 생성하면 그 안에 영속성 컨텍스트 있음
entity 저장: EntityManager.persist(entity)
spring에서 EntityManager 여러 개, 영속성 컨텍스트 1개 존재
entity는 EntityManager를 통해 영속성 컨텍스트에 보관, 관리, 제거된다. 그에 따른 엔티티에 생명주기를 알아보자.
EntityManagerFactory
EntityManager
EntityManagerFactory
에서 생성 가능// hello는 psersistence-unit 이름
EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
// 이를 통해 엔티티를 영속성 컨텍스트에 관리 가능
EntityManager em = emf.createEntityManager();
Member member = new Member(); // 엔티티(객체) 생성
em.persist(member);
em.detach(member);
em.detach(entity);
em.clear()
em.close()
em.remove(member);
영속성 컨텍스트의 장점은 다음과 같다. 하나씩 알아보자.
- 1차 캐시
- 동일성(identity) 보장
- 트랜잭션을 지원하는 쓰기 지연
- 변경 감지
- 지연 로딩
1차 캐시 동작 예시
em.find(Member.class, "member1");
만약 1차 캐시에 찾는 엔티티가 없으면?
em.find(Member.class, "member2");
사실 1차 캐시는 큰 도움이 되지 않는다.
이유1. 1차 캐시가 있는 EntityManager는 트랜잭션 단위로 만들고 사라진다. 즉, 1차 캐시가 살아있는 시간은 매우 짧아 성능에 큰 효과는 없다.
이유2. 트랜잭션마다 각자 EntityManger를 사용한다. 즉, 각자 다른 영속성 컨텍스트와 1차 캐시를 가진다.
예시
// 같은 PK 값 데이터 찾음
// 같은 데이터이지만 저장된 객체는 member1과 member2로 다름
Member member1 = em.find(Member.class, 1L);
Member member2 = em.find(Member.class, 1L);
// 이 때 == 비교를 하면?
System.out.println("result: "+(member1 == member2));
// 결과
result: true
transcation.commit()
em.flush()
em.persist(entity)
를 하면?예시
쓰기 지연 SQL 저장소에 쿼리문 쌓는 과정
em.persist(memberA);
em.persist(memberB)
트랜잭션 커밋이 일어나면?
transcation.commit()
- 트랜잭션 커밋버퍼링 기능
- 모았다가 쿼리 한 번에 보낼 수 있음
- Hibernate의 경우 옵션을 부여 가능
- hibernate.jdbc.batch.size
- 지정한 사이즈만큼 모아서 DB에 한 번에 쿼리 보내고 commit 하는 기능
- ex. 10개 쿼리 모았다가 DB에 반영
<!-- pom.xml에 추가--> <property name="hibernate.jdbc.batch.size" value="10" />
작동 순서
트랜잭션 커밋이 발생하면
flush() 호출
1차 캐시에서 entity와 스냅샷 비교
entity와 스냅샷이 다르다면 쓰기 지연 SQL 저장소에 update 쿼리문 추가
DB에 update 쿼리문 반영 후 commit
예시
Member member = em.find(Member.class, 1L); // name: 홍길동, age = 20
member.setAge(21); // 데이터 변경
트랜잭션 커밋 시점 로그
Hibernate:
/* update
jpabasic.hellojpa.Member */
update
Member
set
name=?
where
id=?
추가
엔티티 삭제는 `em.remove(entity)로 이뤄진다. 위 예시로 든 update와 동일한 방법으로 commit 시점에 delete문이 DB로 날라가 적용된다.
출처 및 참고자료
인프런 '자바 ORM 표준 JPA 프로그래밍 - 기본편' 강의