모각코 7주차 모임 결과 (22.08.18 / 목요일 / 15시 ~ 18시 / Google Meet)

KIMA·2022년 8월 18일
0
post-thumbnail

목표

  • 프로그래머스 강의 듣기

결과

영속성 컨텍스트

: 쿼리를 사용하지 않고도 트랜잭션이 끝나는 시점에 Persistence Context안에 변화가 있는 모든 엔티티 객체를 DB에 자동으로 반영

  • JPA를 이용하는데 가장 중요한 요소
  • EntityManager에 의해 관리됨
    • JPA의 Entity Manager가 활성된 상태이어야 함
  • 영속성 컨텍스트가 엔티티를 관리함으로 얻는 이점
    • 1차 캐시 : 엔터티를 임시 보관
      • DB에서 엔터티를 가져오는 시간을 단축함
      • 1차 캐시에서 key-value로 엔티티를 관리하기 때문에 영속성 컨텍스트 안에서 관리되는 엔티티는 식별자 값을 반드시 가져야함
        • @Id
    • 동일성 보장
    • 트랙잭션을 지원하는 쓰기 지연 : 트랜잭션이 커밋되면 DB에서 쿼리문이 실행됨
    • 변경 감지(dirty check) : 트랜잭션을 커밋하는 순간 영속성 컨텍스트에 있는 엔터티의 변경 내용을 DB에 반영 (FLUSH)
    • 지연 로딩

Entity Manager

: Persistence Context안에서 Entity CRUD 등 Entity와 관련된 모든 일 처리

  • EntityManagerFactory가 thread safe하게 생성
  • Not thread safe

Entity LifeCycle

  • 비영속 (new / transient) : 영속성 컨텍스트와 전혀 관계가 없는 상태
  • 영속 (managed) : 영속성 컨텍스트에 저장된 상태
    • detach : 영속상태의 엔티티를 영속성컨텍스트에서 분리
    • clear : 영속상태의 모든 객체를 영속성컨텍스트에서 분리
    • close : 영속성컨텍스트 종료
  • 준영속 (detached) : 영속성 컨텍스트에 저장되었다가 분리된 상태
  • 삭제 (removed) :엔티티를 영속성컨텍스트에서 분리하고, DB에서도 삭제

Entity CRUD

저장

EntityManager em = emf.createEntityManager(); // 1)엔티티 매니저 생성

EntityTransaction transaction = em.getTransaction(); // 2)트랜잭션 획득
transaction.begin(); // 3)트랙잰셕 begin

Customer customer = new Customer(); // 4-1)비영속
customer.setId(1L);
customer.setFirstName("ayoung");
customer.setLastName("kim");

em.persist(customer); // 4-2)영속화

transaction.commit(); // 5)트랜잭션 commit // EntityManager의 flush()가 실행됨 

조회

  • 1차 캐시를 이용

    @Test
    void 조회_1차캐시_이용() {
      EntityManager em = emf.createEntityManager();
      EntityTransaction transaction = em.getTransaction();
      transaction.begin();
    
      Customer customer = new Customer();
      customer.setId(1L);
      customer.setFirstName("ayoung");
      customer.setLastName("kim");
    
      em.persist(customer);
      transaction.commit();
    
      Customer entity = em.find(Customer.class, 1L); // 1차 캐시에서 조회한다.
      log.info("{} {}", entity.getFirstName(), entity.getLastName());
    }
  • DB를 이용

    @Test
    void 조회() {
      EntityManager em = emf.createEntityManager();
      EntityTransaction transaction = em.getTransaction();
      transaction.begin();
    
      Customer customer = new Customer();
      customer.setId(2L);
      customer.setFirstName("ayoung");
      customer.setLastName("kim");
    
      em.persist(customer);
      transaction.commit();
    
      em.clear(); //영속성 컨텍스트를 초기화 한다.
    
      Customer entity = em.find(Customer.class, 2L); // DB 에서 조회한다. SELECT ...
      log.info("{} {}", entity.getFirstName(), entity.getLastName());
      em.find(Customer.class, 2L); // SELECT Query 수행되지 않는다. 1차캐시 사용
    }

수정

JPA 는 엔티티를 영속성 컨텍스트에 보관할 때, 최초 상태를 복사해서 저장해 두는데 이것을 스냅샷이라 한다. 그리고 플러시 시점에 스냅샷과 엔티티를 비교해서 변경된 엔티티를 찾는다. 만일 스냅샷과 비교하여 변경된 내용이 있을 경우 update Query를 수행한다. (변경 감지는 영속성 컨텍스트가 관리하는 영속 성태의 엔티티에만 적용이 된다.)

@Test
void 수정() {
    EntityManager em = emf.createEntityManager();
    EntityTransaction transaction = em.getTransaction();
    transaction.begin();

    Customer customer = new Customer();
    customer.setId(1L);
    customer.setFirstName("ayoung");
    customer.setLastName("kim");

    em.persist(customer);
    transaction.commit();

    transaction.begin();

    Customer entity = em.find(Customer.class, 1L);
    entity.setFirstName("asdad");
    entity.setLastName("adddddd");

	transaction.commit(); // flush -> UPDATE ... 
}

삭제

@Test
void 삭제() {
    EntityManager em = emf.createEntityManager();
    EntityTransaction transaction = em.getTransaction();
    transaction.begin();

    Customer customer = new Customer();
    customer.setId(1L);
    customer.setFirstName("ayoung");
    customer.setLastName("kim");

    em.persist(customer);
    transaction.commit();

    transaction.begin();

    Customer entity = em.find(Customer.class, 1L);
    em.remove(entity);
    
    transaction.commit(); // flush -> DELETE ..
}

Reference
프로그래머스 백엔드 데브코스

profile
안녕하세요.

0개의 댓글