JPA- 3. 영속성 관리

roon-replica·2022년 8월 4일
0

JPA

목록 보기
3/5

Entity Manager(매니저)

Entity Manager Factory(팩토리)

  • 매니저를 만드는 공장이라고 함
  • 공장은 생성 비용이 크고, 공장에서 매니저를 생성하는 비용은 작다고 함
EntityManagerFactory factory = Persistence.createEntityManagerFactory(...);
// 순수 JPA로 E.M.F 만드는 법;;
// persistence.xml 쓰는 방식은... 후... 좀 별로다

persistence context(pcx)

  • 매니저는 영속성 컨텍스트를 이용해 엔티티를 관리한다고 함

생명주기(상태)

  1. new/transient
    persistence context, DB와 관련없는 순수한 객체 상태
    mapstruct로 변환하거나 팩토리에서 받아왔거나 new로 만들었거나 등등..

  2. managed
    pcx에 저장해서 pcx가 관리하는 엔티티.
    매니저.find()나 JPQL을 사용해서 조회한 엔티티도 managed 상태가 된다고 함!!

  3. detached
    spring jpa에선 detach하는 경우가 있나?

  4. removed
    pcx와 DB에서 삭제? (둘 다에서 삭제하는 건가?)

특징

  • pcx는 엔티티를 식별자 값(@Id로 테이블의 PK와 매핑한 값)으로 구분한다고 함!
    managed 상태가 되려면 식별자 값이 반드시 있어야 함.

  • pcx에서 DB로 저장되는 시점
    트랜잭션을 커밋하는 순간 pcx 내용을 DB에 반영함.
    이것을 flush라고 부름. (DB와 동기화하는 작업)

  • 1차 캐시
    managed 상태의 엔티티는 모두 1차 캐시(메모리 수준)에 저장된다고 함.
    (key, value) = (@Id로 매핑한 식별자값=DB 기본키, 엔티티 객체)

    매니저.find()를 호출하면

    1. 1차 캐시에서 먼저 엔티티를 찾음
    2. 없으면 DB로..
      DB에서 조회해서 엔티티를 생성하고 1차 캐시에 저장 후 엔티티 반환.
      그 엔티티는 managed 상태가 됨

    여러번 조회해도 1차 캐시에서 같은 객체 반환함. (객체 동일성)

  • 트랜잭션 쓰기 지연(transactional write behind)
    엔티티 매니저는 트랜잭션을 커밋하기 직전까지는 내부 쿼리 저장소에 insert sql을 모아둔다고 함..
    트랜잭션을 커밋할 때 모아둔 쿼리를 모두 pcx에서 DB로 flush..

    트랜잭션 내에서는 다 실행되거나, 다 취소되므로 쓰기 지연이 가능함...

  • 변경 감지(dirty checking)
    JPA로 엔티티를 수정할 때는 엔티티를 조회해서 데이터만 변경하면 됨.
    엔티티의 변경사항을 DB에 자동으로 반영하는 기능을 dirty checking이라고 함..

    • 변경 감지 동작 과정

      1. 애플리케이션에서 트랜잭션 커밋, flush() 호출?
      2. 스냅샷(엔티티 최초 상태?)과 엔티티 비교하여 변경된 엔티티 찾기
      3. 변경된 엔티티에 대해 update SQL를 만들어서 쓰기 지연 SQL 저장소에 적재
      4. flush
      5. DB 트랜잭션 commit
    • managed 상태의 엔티티에만 변경감지가 적용된다

    • 기본 update 정책 : 엔티티의 모든 필드 업데이트라고 함..

  • 엔티티를 삭제하면 바로 삭제하지 않고 삭제 SQL을 쓰기 지연 SQL 저장소에 등록한다고 함..
    그리고 트랜잭션이 커밋되어 flush되면 DB로 삭제 SQL을 전달한다고 함..

flush

  • flush 과정

    1. find dirty entity in all managed entity.(dirty checking)
    2. make update sql and send to SQL storage in pcx
    3. send SQLs in SQL storage to DB
  • flush하는 방법

    1. em.flush()?
    2. 트랜잭션 커밋
    3. JPQL 쿼리 실행?

detached(분리된, 준영속)

  • detached 상태에서는 pcx의 관리를 받지 않는다고 할 수 있을 듯?
    detache하면 1차 캐시, 쓰지 지연 SQL 저장소에서 해당 엔티티 관련 모든 정보가 제거된다고 함..

    pcx로부터 detache 됐다는 말임.

  • merge()
    merge()는 그냥 transient/new, detached 상태인 엔티티를 저장하는건데..
    pcx 조회하고, 없으면 DB 조회하고, 없으면 새 엔티티 만들어서....
    managed 상태로 만들고 저장하게 해주는거임

의문점

  • 엔티티 매니저는 여러 스레드가 동시에 접근하면 문제가 발생해서 스레드 간에 공유하면 안 된다고 함.
    왜 스레드 간에 공유가 안 될까?
    -> 덮어쓰고 그러겠지만... 정확한 이유는 모름

  • 엔티티 매니저는 DB 연결이 꼭 필요한 시점까지 커넥션을 얻지 않는다?
    어떤 원리이길래 이렇게 동작하는지?

  • persistence context에서 detached랑 removed 차이 명확히 모름
    managed인 엔티티를 제거하면 detached? removed?

  • 준영속(detached) 상태는 언제 쓰이나?
    new/transient가 식별자값 가지고 있으면 detached 상태나 마찬가지라 보면 될듯

  • 원리도 좋지만.. spring jpa 관점에서 살펴봐야..

profile
집중 ➝ 프로세서↑ 시간 투자 ➝ 디스크↑

0개의 댓글