본문 바로가기
Back-End/Spring Data

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

by 두두리안 2021. 1. 5.
728x90

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

  • 목차
    • 1.영속성 컨텍스트1
    • 2.영속성 컨테스트2
    • 3.플러시
    • 4.준영속상태
    • 5.정리

1.영속성 컨텍스트1

  • 객체와 관계형 데이터베이스 매핑
  • 영속성 컨텍스트

영속성 컨텍스트

  • 엔티티를 영구 저장하는 환경
EntityManager.persist(entity)
  • persist 는 DB 에 저장이 아닌 영속성 컨텍스트에 저장한다
  • 논리적인 개념 , 눈에 보이지 않는다 , 엔티티 매니저를 통해서 접근

영속성 컨텍스트

  • 비영속 : 새로운 상태
  • 영속 : 관리하는 상태
  • 준영속 : 분리된 상태
  • 삭제 : 삭제된 상태

비영속성 상태

  • 객체를 생성한 상태
Member member = new Member();
member.setId("memberId");
member.setUsername("회원");

영속성 상태

  • 객체를 저장한 상태
em.persist(member)

비영속,영속

public class JpaMain {

    public static void main(String[] args) {

        EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");

        EntityManager em = emf.createEntityManager();
        EntityTransaction tx = em.getTransaction();
        tx.begin();

        try{
            //비영속
            Member member = new Member();
            member.setId(100L);
            member.setName("HelloJpa");

            //영속
            em.persist(member);

            tx.commit();
        }catch (Exception e){
            tx.rollback();
        }finally {
            em.close();
        }
        emf.close();
    }
}
  • DB 는 tx.commit() 시점에서 쿼리가 날아간다

준영속 상태

  • 영속성 컨텍스트에서 분리
em.detach(member)

삭제 상태

  • 객체를 삭제한 상태
em.remove(member)

영속성 컨텍스트 이점

  • 1차캐시
  • 동일성
  • 트랜잭션을 지원하는 쓰기 지연
  • 변경감지
  • 지연로딩

2.영속성 컨테스트2

1차 캐시

  • 영속성 컨텍스트는 조회할때 1차캐시를 찾아본다
  • 1차캐시에 값이 있으면 반환
  • 영속성 컨텍스트는 조회할때 1차캐시를 찾아본다
  • 1차캐시에 값이 없으면 DB 에서 조회한다음 가져와서 1차캐시에 저장하고 반환한다

영속 엔티티의 동일성 보장

public class JpaMain {

    public static void main(String[] args) {

        EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");

        EntityManager em = emf.createEntityManager();
        EntityTransaction tx = em.getTransaction();
        tx.begin();

        try{

            Member findMember1 = em.find(Member.class, 101L);
            Member findMember2 = em.find(Member.class, 101L);

            System.out.println("result = " + (findMember1==findMember2));

            tx.commit();
        }catch (Exception e){
            tx.rollback();
        }finally {
            em.close();
        }
        emf.close();
    }
}

image

  • 조회는 1번만 된다
  • findMember1==findMember2 결과값은 true

엔티티 등록할때 트랜잭션을 지원하는 쓰기 지연가능

  • 1차캐시 -> 쓰기지연 SQL 저장소 -> 트랙재션 커밋됨 -> Insert 문 나간다
public class JpaMain {

    public static void main(String[] args) {

        EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");

        EntityManager em = emf.createEntityManager();
        EntityTransaction tx = em.getTransaction();
        tx.begin();

        try{

            Member member1 = new Member(150L, "A");
            Member member2 = new Member(160L, "B");

            em.persist(member1);
            em.persist(member2);

            System.out.println("=====================");

            tx.commit();
        }catch (Exception e){
            tx.rollback();
        }finally {
            em.close();
        }
        emf.close();
    }
}

image

  • persist 되도 쓰기지연 sql 저장소에 보관
  • tx.commit() 되는 순간 Insert SQL 문이 날아간다

변경감지

public class JpaMain {

    public static void main(String[] args) {

        EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");

        EntityManager em = emf.createEntityManager();
        EntityTransaction tx = em.getTransaction();
        tx.begin();

        try{

            Member member = em.find(Member.class, 150L);
            member.setName("hello");

            System.out.println("=====================");

            tx.commit();
        }catch (Exception e){
            tx.rollback();
        }finally {
            em.close();
        }
        emf.close();
    }
}

image

  • 1차캐시에서 조회 한다
  • tx.commit 되면서 Update 문이 나간다
  • JPA 는 변경을 감지해줘서 Update 해준다 (더티체킹)
    • tx.commit 되기전에 flush 가 일어난다
    • flush 를 통해서 엔티티와 스냅샷을 비교
    • 스냅샷 - 최초의 영속성 컨텍스트 값
    • 변경된 부분을 쓰기지연 SQL 문 저장소에 Update 해준다
    • 실제 DB 에 Update 된다

3.플러시

  • 영속성 컨텍스트의 변경내용을 데이터베이스에 반영
  • 변경감지 -> 쓰기지연 sql 저장소에 등록 -> DB 에 전송
  • em.flush , 트랜잭션 커밋 , JPQL 실행
public class JpaMain {

    public static void main(String[] args) {

        EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");

        EntityManager em = emf.createEntityManager();
        EntityTransaction tx = em.getTransaction();
        tx.begin();

        try{

            Member member = new Member(200L, "member200");
            em.persist(member);

            em.flush();

            System.out.println("=====================");

            tx.commit();
        }catch (Exception e){
            tx.rollback();
        }finally {
            em.close();
        }
        emf.close();
    }
}

image

  • 결과를 보면 트랜잭션 커밋하기 전에 Insert 문이 들어갔다
  • flush 되도 1차캐시는 안지워 진다

JPQL 쿼리 실행시 플러시가 자동으로 호출되는이유

  • JPQL 은 DB 에서 가져와야 실행된다
  • 무조건 flush 를 쓰고 가져온다

플러시 정리

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

4.준영속상태

  • 영속 -> 준영속
  • 영속 상태의 엔티티가 영속성 컨텍스트에서 분리
  • 영속성 컨텍스트가 제공하는 기능을 사용못함
public class JpaMain {

    public static void main(String[] args) {

        EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");

        EntityManager em = emf.createEntityManager();
        EntityTransaction tx = em.getTransaction();
        tx.begin();

        try{

            Member member = em.find(Member.class, 150L);
            member.setName("hello hello");

            em.detach(member);

            System.out.println("=====================");

            tx.commit();
        }catch (Exception e){
            tx.rollback();
        }finally {
            em.close();
        }
        emf.close();
    }
}

image

  • em.detach(member) 을 이용해서 준영속 제거
  • 변경을 감지했지만 Update 문이 안나가것을 확인할수 있다
  • em.detach - > 특정 엔티티 만 준영속
  • em.clear -> 모두 초기화
  • em.close -> 영속성 컨텍스트를 종료

참고

https://www.inflearn.com/course/ORM-JPA-Basic/dashboard

image

728x90

'Back-End > Spring Data' 카테고리의 다른 글

4.엔티티 매핑  (0) 2021.01.07
2.JPA 시작하기  (0) 2021.01.04
1.JPA 소개  (0) 2021.01.04
9.웹 계층 개발 2(주문)  (0) 2021.01.01
8.변경감지 와 병합  (0) 2021.01.01