ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • JPA 영속성 컨텍스트 내부동작
    카테고리 없음 2020. 3. 19. 21:55

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

    웹 어플리케이션을 개발 한다고 하면 고객의 요청이 올때마다 entityManager를 생성하고
    이 엔티티매니저는 내부적으로 db 커넥션을 맺는다

    2.그러면 영속성 컨텍스트란 뭔가?

    엔티티를 영구 저장하는 환경이라는 뜻.

    눈에 보이지 않는 어떤 논리적인 개념.
    EntityManager.persist(entity); => 영속성 컨텍스트를 통해 entity를 영속화한다.
    엔티티매니저를 통해서 영속성 컨텍스트에 접근한다.


    3.엔티티의 생명주기

    1. 3-1.비영속 (new/transient)
      영속성 컨텍스트와 전혀 관계가 없는 새로운 상태
    2. 3-2.영속(managed)
      영속성 컨텍스트에 관리되는 상태
    3. 3-3.준영속(detached)
      영속성 컨텍스트에 저장되었다가 분리된 상태
    4. 3-4.삭제(removed)
      삭제된 상태

    3-1.비영속상태

    비영속상태는 멤버 객체를 생성하고 내가 엔티티매니저에 아무것도 안한상태. JPA에 관계없이 객체만 생성한 상태.


    3-2 영속상태

    em.persist(member)를 하면 여기서부터 이제 영속 상태가 된다.

    entityManager안의 영속성컨텍스트를 통해 이 entity가 관리 되게 된다.

    ※em.persist하면 DB에 쿼리가 날라가는게 아니라 트랜잭션을 commit()을 한 시점에 DB에 쿼리가 날라감.


    3-3 준영속

    em.detach() 하면 영속성 컨텍스트에서 지움.

    3-4 삭제

    실제 DB에서 삭제하는거


    4 .엔티티 조회, 1차 캐시란?

    @Id값이 key, memeber 객체가 value가 된다.

    em.persist(member);를 하게 되면 영속성 컨텍스트 안의 1차 캐시에 저장을 한다. 그리고 commit을 하면 db에 보냄.

    조회시에는 바로db에 가서 조회 해오는게 아니라 1차 캐시에 있는지 확인해서 있으면 1차 캐시에서 조회해옴.

    ※애플리케이션 전체가 공유하는 캐시가 아니라 한 트랜잭션 안에서만 공유하는 캐시라서 성능상의 엄청난 이득은 없음.


    5. 엔티티 등록 트랜잭션을 지원하는 쓰기 지연

    
    em.persist(memberA);
    
    em.persist(memberB);
    

    할때 insert문을 데이터베이스에 보내는게 아니라 커밋하는 순간 데이터베이스에 INSERT SQL을 보낸다

    영속성컨텍스트 안에는 1차캐시외에도 쓰기 지연 SQL 저장소라는 것도 있음.
    em.persist(memberA)를 넣으면 JPA안에서는 1차캐시에 저장을 한다.
    그러면서 JPA가 entity를 분석해서 INSERT 쿼리를 생성한다.

    그러고 쓰기 지연 SQL저장소에 쌓아둔다. (DB에는 아직 안넣음)

    em.persist(memberB)도 마찬가지!

    그럼 언제 db에 insert되나? transaction.commit(); 하는 시점에
    쓰기 지연 SQL 저장소에 있던 애들이 flush가 되면서 날라간다.


    6.변경감지(==dirty checking)

    em.persist(memberA); 를 하면 1차 캐시에 저장이 되고 db에 insert는 transaction.commit() 할 때 한다고 했다.

    그럼 수정을 할 때는?

    em.persist(memberA);가 insert, 저장 같은 느낌이라 update할 때에는 em.update(memberA)와 같은 코드가 있을 것 같지만 업데이트 할 때는 em.persist(memberA); 도 em.update(memberA) 하지 않는다

    만약 memberA의 UserName을 바꾼다고 한다면

    ```

    memberA.setUsername("hi");

    ```

    위에 처럼바꾸면 끝이다. JPA는 어떻게 위의 코드만으로 db에 update를 하는 것일까?

    JPA는 트랜잭션을 커밋하는 시점에 내부적으로 flush를 한다.

    그다음 엔티티와 스냅샷을 비교한다.

    스냅샷이란? 1차캐시안에는 @Id 와 Entity와 스냅샷이 있다.

    최초로 영속성 컨텍스트에 들어왔을 때(insert 등으로) JPA가 딱 스냅샷을 떠둔다.

    그 상태에서 memberA의 값을 memberA.setUsername("hi"); 이런식으로 변경하면

    트랜잭션을 커밋한 시점에 스냅샷과 entity를 비교한다.

    일일히 내부적으로 비교해서 다르면? update쿼리를 쓰기 지연 sql저장소에 만들어두고

    db에 보내 반영한다. 이걸 변경감지라고 한다


    **JPA는 값을 바꾸면 트랜잭션이 커밋되는 시점에 그거를 반영하는구나.

    **라고생각해야한다

    **.update() 이런거없다.

    댓글

Designed by Tistory.