[JPA] 영속성 관리 - 내부 동작 방식

·2024년 4월 11일
0

JPA

목록 보기
1/17
post-thumbnail

💡영속성 컨텍스트

  • jpa를 이해하는데 가장 중요한 용어
  • 엔티티를 영구 저장하는 환경이라는 뜻
  • EntityManager.persist(entity);
  • 엔티티 매니저를 통해 영속성 컨텍스트에 접근한다.

💡엔티티의 생명 주기

📗1. 비영속(new/transient)

영속성 컨텍스트와 전혀 관계가 없는 새로운 상태

	//비영속
	Member member = new Member();
	member.setId(101L);
	member.setName("HelloHJPA");
  • member 객체를 생성했을 뿐, 영속성 컨텍스트에 관리 되는 상태는 아니다.

📗2. 영속(managed)

영속성 컨텍스트에 관리되는 상태

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

	//영속
	em.persist(member);
  • em.persist(member);로 member객체를 영속성 컨텍스트에 저장함.

📗3. 준영속(detached)

영속성 컨텍스트에 저장되었다가 분리된 상태

	em.detach(member);
  • member 객체를 em.detach(member);로 영속성 컨텍스트에서 분리함.

📗4. 삭제(remove)

삭제된 상태

	em.remove(member);

💡영속성 컨텍스트의 이점

📗1. 1차 캐시

  • em.persist(member);를 할 때, JPA는 1차 캐시에 member1가 들어있는지 확인한다.
  • 1차 캐시에 들어가 있지 않으면, 1차캐시에 member1을 저장한다.
  • em.find()로 member1을 조회할 때, JPA는 제일 먼저 1차 캐시를 확인하고, 1차 캐시에 member1이 있으면 1차 캐시에서 조회한다.

  • member2를 조회했을 때, JPA는 제일먼저 1차 캐시를 확인한다.

  • 1차 캐시에 없다면 DB를 조회하게 된다.

  • DB에서 찾은 member2를 1차 캐시에 저장 후, 반환한다.

📗2. 영속 엔티티의 동일성 보장

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

System.out.println(a == b); //true
  • JPA는 같은 레퍼런스의 객체면 엔티티의 동일성을 보장해준다.

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

(1) memberA가 1차 캐시에 저장된다.
(2) 동시에 JPA가 해당 엔티티를 분석해서 INSERT SQL을 생성
(3) 생성한 INSERT SQL을 쓰기 지연 SQL 저장소에 담아둔다.
(4) 멤버 B도 1차 캐시에 저장된다.
(5) 멤버 A와 마찬가지로 JPA가 INSERT SQL을 생성
(6)생성한 INSERT SQL을 쓰기 지연 SQL 저장소에 차곡차곡 담아둔다.
(7)쓰기 지연 SQL 저장소에 쌓아둔 쿼리들이 커밋이 되면 fulsh가 되면서 실제 데이터베이스 트랜잭션이 커밋됨.

📗4. 변경 감지(Dirty Checking)

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

//영속 엔티티 데이터 수정
memberA.setUserName("aaa");
memberA.setAge("10");
  • JPA는 마치 자바 컬렉션을 다루듯 객체를 다룬다.
  • 위 코드와 같이 setter를 이용해서 데이터의 변경이 감지되면 JPA는 데이터를 자동으로 변경해준다.

(1) 스냅샷이란 값을 읽어온 최초 시점의 상태를 저장하는 공간이다.
(2) JPA가 트랜잭션을 커밋하는 시점에 내부적으로 flush()가 호출되면서 스냅샷엔티티를 비교한다.
(3) UPDATE SQL을 생성 한 후 쓰기 지연 SQL 저장소에 담아둔다.
(4) UPDATE 쿼리를 데이터베이스에 반영하고 커밋을 한다.

💡플러시

영속성 컨텍스트의 변경 내용을 데이터베이스에 반영한다.

📗플러시가 발생하면?

  • 변경 감지
  • 수정된 엔티티 쓰기 지연 SQL 저장소에 등록
  • 쓰기 지연 SQL 저장소의 쿼리를 데이터 베이스에 전송

📗영속성 컨텍스트를 플러시하는 방법

  • em.flush() : 직접 호출
  • 트랜잭션 커밋 : 플러시 자동 호출
  • JPQL 쿼리 실행 : 플러시 자동 호출

📌플러시는!

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

💡준영속 상태

  • 영속 -> 준영속
  • 영속 상태의 엔티티가 영속성 컨텍스트에서 분리 detached
  • 영속성 컨텍스트가 제공하는 기능 사용 불가

📗준영속 상태로 만드는 법

  • em.detach(entity) : 특정 엔티티만 준영속 상태로 전환
  • em.celar() : 영속성 컨텍스트를 완전히 초기화
  • em.close() : 영속성 컨텍스트를 종료
profile
백엔드 개발자를 꿈꿉니다 / 이전 블로그 : https://po-dadak.tistory.com/category

0개의 댓글

관련 채용 정보