본문 바로가기
JAVA

[JPA] 엔티티의 생명주기 - 영속, 비영속, 준영속, 삭제

by 고 민 2024. 1. 10.
728x90
반응형

 

엔티티생명주기

JPA 엔티티의 생명주기에 대해 알아보자.

엔티티 생명주기에는 영속, 비영속, 준영속, 삭제 총 4가지 상태가 있다.

비영속 (new/transient)

영속성 컨텍스트와 관계 없는 새로운 상태를 말한다. 즉, 영속성 컨텍스트 관리되기 이전의 상태.

영문 표기는 transient 인데 '일시적인' 이라는 뜻이 있다. 

데이터베이스 영속성이 부여되기 전인 일시적인 상태를 의미한다. 

======================
member.getId() = 1
======================
Hibernate: 
    /* insert jpashop.jpashop.domain.Member
        */ insert 
        into
            Member
            (city, USERNAME, street, TEAM_ID, zipcode, MEMBER_ID) 
        values
            (?, ?, ?, ?, ?, ?)
1월 10, 2024 9:48:31 오후 org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl$PoolState stop
INFO: HHH10001008: Cleaning up connection pool [jdbc:h2:tcp://localhost/~/test]

Process finished with exit code 0

영속 (Managed)

엔티티가 영속성 컨텍스의 관리 대상이 된 상태.

EntityManager의 persist() 메서드의 파라미터로 넘겨지는 객체는 JPA(영속성 컨텍스트)가 관리하게 되며,  영속 상태에 들어간다. 

/*생략*/

Member member = new Member();
member.setId(1L);
member.setName("chan");


System.out.println("======================");
//영속
em.persist(member);

System.out.println("member.getId() = " + member.getId());
System.out.println("======================");


tx.commit();

/*생략*/

아래 실행결과에서 주석이 먼저 출력된 후에 insert문이 실행 되는 것을 볼 수 있다. 

영속성 컨텍스트의 관리를 받게되는 동시에 INSERT 쿼리를 생성해 쓰기 지연 SQL 저장소라는 공간에 넣고, 이렇게 생성된 SQL은 commit 시점에 일괄 실행된다. 

======================
member.getId() = 1
======================
Hibernate: 
    /* insert jpashop.jpashop.domain.Member
        */ insert 
        into
            Member
            (city, USERNAME, street, TEAM_ID, zipcode, MEMBER_ID) 
        values
            (?, ?, ?, ?, ?, ?)
1월 10, 2024 9:48:31 오후 org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl$PoolState stop
INFO: HHH10001008: Cleaning up connection pool [jdbc:h2:tcp://localhost/~/test]

Process finished with exit code 0

준영속(Detached) 

영속성 컨텍스트로부터 분리된 상태.

영속성 컨텍스트가 제공하는 모든 기능을 이용할 수 없는 상태가 된다. 

Member member = new Member();
member.setId(1L);
member.setName("chan");


System.out.println("======================");
//영속
em.persist(member);

System.out.println("member.getId() = " + member.getId());
System.out.println("======================");


em.detach(member);


Member findMember = em.find(Member.class, 1L);
System.out.println("findMember = " + findMember.getId());

select문은 나가지만 

아래 결과에서 find()를 통해 select쿼리는 만들어 지지만 객체를 조회해오지 못해 NullPointerException이 발생한다. 

======================
member.getId() = 1
======================
Hibernate: 
    select
        member0_.MEMBER_ID as member_i1_0_0_,
        member0_.city as city2_0_0_,
        member0_.USERNAME as username3_0_0_,
        member0_.street as street4_0_0_,
        member0_.TEAM_ID as team_id5_0_0_,
        member0_.zipcode as zipcode6_0_0_ 
    from
        Member member0_ 
    where
        member0_.MEMBER_ID=?
java.lang.NullPointerException: Cannot invoke "jpashop.jpashop.domain.Member.getId()" because "findMember" is null
	at jpashop.jpashop.JpaMain.main(JpaMain.java:40)

삭제(removed) 

영속성 컨텍스트에서 객체가 완전히 삭제된 상태이다.

Member member = new Member();
member.setId(1L);
member.setName("chan");


System.out.println("======================");
//영속
em.persist(member);

System.out.println("member.getId() = " + member.getId());
System.out.println("======================");


// 삭제
em.remove(member);


Member findMember = em.find(Member.class, 1L);
System.out.println("findMember = " + findMember.getId
tx.commit();

detach와 달리 find쿼리 자체가 실행되지 않고, nullponterException이 발생한다. 

======================
member.getId() = 1
======================
java.lang.NullPointerException: Cannot invoke "jpashop.jpashop.domain.Member.getId()" because "findMember" is null
	at jpashop.jpashop.JpaMain.main(JpaMain.java:41)

 

 

reference

자바 ORM 표준 JPA 프로그래밍

https://www.inflearn.com/course/lecture?courseSlug=ORM-JPA-Basic&unitId=21687

728x90
반응형