HomeAboutMeBlogGuest
© 2025 Sejin Cha. All rights reserved.
Built with Next.js, deployed on Vercel
📝
남득윤 학습 저장소
/
자바 ORM 표준 JPA 프로그래밍 - 기본편
자바 ORM 표준 JPA 프로그래밍 - 기본편
/
3️⃣
3. 영속성 관리 - 내부 동작 방식
3️⃣

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

 

엔티티 매니저 팩토리와 엔티티 매니저

EntityManagerFactory

  • Entity를 관리하는 EntityManager 를 생산하는 공장
  • ThreadSafe 하다.
 

EntityManager

  • EntityManager는 Entity를 저장, 수정, 조회, 삭제 (CRUD)등 Entity와 관련된 모든 일을 처리
  • ThreadSafe 하지 않음
    • 여러 Thread에서 동시에 접근 할 경우 동시성 이슈가 발생할 수 있다.
 
엔티티 매니저는 트랜잭션을 시작할 때, 커넥션을 획등한다.
엔티티 매니저는 트랜잭션을 시작할 때, 커넥션을 획등한다.
 

영속성 컨텍스트

  • 엔티티를 영구 저장(영속화)하는 환경
  • em.persist(entity);
엔티티는 엔티티매니저에 의해 영속성 컨텍스트에서 관리된다.
엔티티는 엔티티매니저에 의해 영속성 컨텍스트에서 관리된다.
  • 논리적인 개념이다.
  • 엔티티 매니저를 통해서 영속성 컨텍스트에 접근

영속성 컨텍스트의 특징

  • 식별자 값
    • 영속성 컨텍스트 안에서 관리되는 엔티티는 식별자 값을 반드시 가져야 한다.
    • key-value로 엔티티를 관리하기 때문이다.
  • 영속성 컨텍스트와 DB 저장
    • JPA는 트랜잭션을 커밋하는 순간 영속성 컨텍스트에 새로 저장된 엔티티를 DB에 반영한다. (flush)
    • 플러시(flush)는 영속성 컨텍스트의 변경내용을 db에 동기화 하는 작업이다.
  • 영속성 컨텍스트가 엔티티를 관리함으로 얻는 이점
    • 1차 캐시
    • 동일성 보장
    • 트랜잭션을 지원하는 쓰기 지연
    • 변경 감지
    • 지연 로딩
 

엔티티의 생명주기

  • 비영속 (new/transient)
Member member = new Member();
  • 영속(managed) - 영속성 컨텍스트에 추가
Member member = new Member(); //member 객체가 영속성 컨텍스트에서 관리된다. em.persist(member);
  • 준영속(detached) - 영속성 컨텍스트에서 분리
Member member = new Member(); member.setId(1L); //영속상태의 customer객체를 영속성컨텍스트에서 분리한다. em.detach(member); //영속상태의 모든 객체를 영속성컨텍스트에서 분리한다. em.clear(); //영속성 컨텍스트를 종료한다. em.close();
 
  • 삭제(removed) - db에서 delete
//영속성 컨텍스트에서 분리하고 db에서도 삭제한다. em.remove(member);

영속성 컨텍스트의 이점

1차 캐시 - 한 트랙젝션 내에서의 캐시기능

Member member = new Member(); member.setId(102L); member.setName("HelloA"); em.persist(member); Member findMember = em.find(Member.class, 102L); System.out.println("findMember.getId() = " + findMember.getId()); System.out.println("findMember.getName() = " + findMember.getName()); tx.commit();
→ select 쿼리 안나감!!!!!
 
이미 102번 멤버가 있을때
Member findMember1 = em.find(Member.class, 102L); System.out.println("findMember1 = " + findMember1); Member findMember2 = em.find(Member.class, 102L); System.out.println("findMember2 = " + findMember2); tx.commit();
→ select 쿼리 한방!!

심지어 findMember의 동일성 보장!!

findMember1 = Member@1894e40d findMember2 = Member@1894e40d

트랜잭션을 지원하는 쓰기 지연

em.persist(memberA); em.persist(memberB); tx.commit(); // em.flush()-> 여기서 Insert Query 두방!!
notion image
notion image
 

변경 감지

데이터 수정을 컬렉션처럼! dirty checking!
notion image
커밋 직전 (flush하면) 앤티티와 스냅샷을 비교
 
JPA는 엔티티를 영속성 컨텍스트에 보관할 때 최초 상태를 복사해서 저장해 두는데 이것을 스냅샷이라 한다. 그리고 플러시 시점에 스냅샷과 엔티티를 비교해서 변경된 엔티티를 찾는다. 만약 스냅샷과 비교하여 변경된 내용이 있을 경우 update Query를 수행한다. (변경 감지는 영속성 컨텍스트가 관리하는 영속 상태의 엔티티에만 적용이 된다.)
@)See Also
🆚
변경 감지와 병합(merge)

플러시

영속성 컨텍스트의 변경 내용을 DB에 반영
 
플러시 →
  • 변경감지
  • 변경된 엔티티의 수정 쿼리를 쓰기 지연 SQL저장소에 등록
  • 쓰기 지연 SQL 저장소의 쿼리를 DB에 전송 (등록, 수정, 삭제)
  • 1차 캐시는 유지된다 (영속성 컨텍스를 비우는 것이 아님)
em.flush() - 직접 실행
tx.commit()- 자동 실행
jpql 쿼리 - 자동 실행
 

준영속 상태

  • 영속 → 준영속
  • 영속성 컨텍스트에서 분리
  • 영속성 컨텍스트의 기능 사용안함
em.detach(entity) - 특정 엔티티를 영속 상태에서 제거 em.clear() - 영속성 컨텍스트를 완전히 초기화
em.close() - 영속성 컨텍스트 종료

원래
요청 시작 : db connection 시작
→ 요청 끝 : db connection 종료
 
OSIV false
@Transactional 시작 : db connection 시작
→ @Transactional 탈출 : db connection 종료
 
OSIV true
@Transactional 시작 db connection 시작
→ 요청 끝 : db connection 종료