[항해 취업코스] 개발자 취준 기록 2일차 - 엔티티 객체 생명주기

Godtaek·2024년 3월 6일
0

Spring

목록 보기
6/9

1. 서론

1일차에서 더티 체킹을 공부하며 영속 상태만 되니, 비영속, 준영속은 영속성 컨텍스트가 관리하지 않아서 더티 체킹이 안된다느니... 실제로 JPA에서 가장 중요한 개념 중 하나가 영속성 컨텍스트라고 생각한다. 그렇게 배웠다.

영속성 컨텍스트를 공부하기에 앞서 영속 상태가 뭔지, 엔티티 객체가 JPA 코드로 어떻게 관리되는지 라이프싸이클을 알아보자.

2. 코드로 보는 생명주기

위 사진이 엔티티 객체의 라이프싸이클을 모두 담고 있다.
하나하나 알아볼 것이다. @Transactional을 사용하면 자동으로 엔티티의 생명주기가 돌아가기 때문에 EntityManager를 활용할 것이다.

1. New/Transient(비영속 상태)

  • 객체가 생성되어 메모리에 올라갔지만, 영속성 컨텍스트랑 상관이 없는 상태다.

  • persist() 메서드를 통해 영속상태로 만들어줄 수 있다.

EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("myEntityObjectTest");
EntityManager em = entityManagerFactory.createEntityManager();

// 비영속 상태
Book book = new Book();
book.setName("1번책");
book.setContent("1번책 내용");
  • 객체를 생성하고, 값을 세팅한 상태다. 아직 엔티티 매니저랑은 상관이 없다.

  • 어? 1일차에서 저렇게만 해도 더티체킹이 된다고...?
    - @Transactional은 자동으로 비영속 / 영속 / 준영속 / 제거 상태로 만든다. 현재 EntityManager를 사용하기 때문에 영속상태가 되려면 메서드를 불러와야 한다.

2. Managed(영속 상태)

  • 엔티티 매니저에 의해 영속성 컨텍스트에 관리되고 있는 상태

  • 엔티티 매니저를 사용하여 엔티티를 조회하거나 저장하면, 해당 엔티티는 자동으로 관리 상태로 전환

  • persist()메서드를 사용하여 영속 상태로 만들 수 있다.

  • remove(), detach() 등 메서드로 삭제, 준영속 상태로 만들 수 있다.

  • 영속 상태를 비영속 상태로는 만들 수 없다.

  // 트랜잭션 시작
EntityTransaction transaction = em.getTransaction();
transaction.begin();

try {
   // 영속 상태
   em.persist(book);

   // 커밋
   transaction.commit();
} catch (Exception e) {
   if (transaction.isActive()) {
        transaction.rollback();
   }
  • 간단하게 생성한 객체를 persist()함수의 인자로 넣어 영속 상태로 만들 수 있다.

  • find()를 통해서 찾았다면 그 역시 영속 상태로 관리한다.

3. Detached(준영속 상태)

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

  • 비영속 상태와 유사하지만 가장 다른점은 영속성 컨텍스트 식별자 유무다. 영속성 컨텍스트에서 관리된 적있는 준영속 상태는 식별자가 존재한다.

  • close(), clear(), detach() 함수로 준영속상태로 만들 수 있다. 각각 역할이 다르다.

  • close()는 영속성 컨텍스트 종료 메서드다. 종료 후 영속 상태 객체들은 당연히 분리된다.

  • clear()은 영속성 컨텍스트에서 관리하는 객체를 모두 제거하여 준영속 상태로 만든다.

  • detach()는 특정 엔티티를 영속성 컨텍스트에서 분리하는 메서드다.

finally {
    // 준영속 상태 
    em.detach(book);
 }
  • clear(), close()를 사용해도 준영속 상태로 만들 수 있다.

  • 굳이 사용해본 적 없다. 개발자가 준영속 상태를 명시하는 일이 적다고 한다.

https://stackoverflow.com/questions/31446/detach-an-entity-from-jpa-ejb3-persistence-context

  • 위 질문과 같이, 엔티티 매니저에서는 변하지 않고, 어플리케이션에서만 데이터를 변하게 하고 싶을 때 사용하는 것 같다. evict라는 메서드가 존재했던 것 같은데, 현재는 존재하지 않는다.
book.setContent("사실 2번책임");
em.merge(book);
  • merge()메서드를 통해서 영속 상태로 바꿔줄 수 있다.

준영속은 왜 존재하는가?

준영속이 왜 필요한지 궁금해서 찾아봤다. 명확한 답변은 얻기 힘들었다.

https://stackoverflow.com/questions/21622841/why-need-detached-entities-in-jpa

궁금한 사람이 나뿐은 아니었나보다.

원래는 1차 캐시에 너무 많은 데이터가 입력되면 OutOfMemoryException이 나기 때문에, clear(), evict(지금의 detach())를 사용하여 관리하려고 만들었다.

그럼 굳이 식별자를 안 가져도 되는 거 아닌가

굳이 준영속 상태를 사용하는 이유를 찾아봤는데

  1. 영속성 컨텍스트와 분리하고 나서 어플리케이션 단위에서 객체를 바꾸고 싶을 때
  2. 엔티티를 가져와서 유효성 검사만 하고 싶을 때
  3. 엔티티의 일부 필드만 가져와서 일부 필드만 update하고 싶을 때(@DynamicUpdate) -> 기본적으로 영속성 컨텍스트에서 관리하면 모든 필드를 update하기 때문

4. removed(삭제)

  • DB와 영속성 컨텍스트에서 해당 엔티티를 삭제한다.

  • 영속 상태일때만 가능하다.

em.remove(book);
  • persist()를 통해서 영속 상태로 전환 가능하다.

5. 정리

  1. 엔티티 객체는 비영속 -> 영속 -> 준영속 or 삭제 순서대로 생명주기가 존재한다.

  2. @Transactional을 사용한다면 Spring-data-Jpa가 알아서 관리해주지만, 그래도 잘 사용하기 위해서 알아두는 편이 좋다.

3. 마치며

다음은 영속성 컨텍스트다. 뭔가 거슬러 가는 느낌이긴하다.

근데 진짜 준영속 상태가 왜 필요한가요?


항해 개발자 취업 리부트 코스를 수강하고 작성한 콘텐츠 입니다.

profile
성장하는 개발자가 되겠습니다

0개의 댓글