비영속(Transient) 상태
쉽게 말하자면 `new` 연산자를 통해 인스턴스화 된 Entity 객체
아직 영속성 컨텍스트에 저장되지 않았기 때문에 JPA의 관리를 받지 않는다.
Memo memo = new Memo(); // 비영속 상태
비영속 상태 때는 `entitiesByKey=null`이다.
JPA가 관리할 수 없어서 해당 객체의 데이터를 변경해도 변경 감지가 이루어지지 않는다.
영속(Managed) 상태
관리하고 싶은 객체를 `persist`에 던져서 넣으면,
영속성 컨텍스트에 저장하여 (EntityManager를 통해) 관리되고 있는 상태로 만든다.
em.persist(memo); // 영속 상태
준영속(Detached) 상태
영속성 컨텍스트에 저장되어 관리되다가 비영속 상태로 분리된 상태이다.
[영속 상태 -> 준영속 상태]
3가지 메서드
1. `detach(entity)`
특정 entity를 준영속 상태로 만들어 준다.
--em.find(Memo.class, 1);
Hibernate:
select
m1_0.id,
m1_0.contents,
m1_0.username
from
memo m1_0
where
m1_0.id=?
-- sout으로 출력해보기
memo.getId() = 1
memo.getUsername() = Robbie
memo.getContents() = 비영속과 영속 상태
--em.contains()로 영속성 컨텍스트에 저장되어 관리되는 상태인지 확인
em.contains(memo) = true
detach() 호출
--em.detach(memo);
--준영속 상태로 전환(managed상태가 아니라서 dirty checking이 안됨)
em.contains(memo) = false
memo Entity 객체 수정 시도
트랜잭션 commit 전
트랜잭션 commit 후
-- 아무것도 되지 않는다.
2. `clear()`
호출 시 컨텍스트를 완전히 초기화한다. 영속성 컨텍스트에 있던 모든 enttiy를 준영속 상태로 전환
다시 영속상태로 전환이 가능하다. 비우고 다시 사용
3. `close()`
완전히 종료시키는 메서드(clear()와 다른점)
[준영속 상태 -> 영속 상태]
1. `merge(entity)` : 전달받은 Entity를 사용하여 새로운 영속 상태의 Entity를 반환
em.merge(memo);
동작 방식
-파라미터로 전달된 Entity의 식별자 값으로 영속성 컨텍스트를 조회
- 해당 Entity가 영속성 컨텍스트에 없다면?
a. DB에서 새롭게 조회
b. 조회한 Entity를 영속성 컨텍스트에 저장
c. 전달 받은 Entity의 값을 사용하여 병합
d. Update SQL 수행(수정) - 만약 DB에도 없다면
a. 새롭게 생성한 Entity를 영속성 컨텍스트에 저장
b. Insert SQL이 수행(저장)
따라서 `merge()`메서드는 비영속, 준영속 모두 파라미터로 받을 수 있으면, 상황에 따라 수정, 저장 모두 가능하다.
Memo memo = new Memo();
// 중간 set 생략
Memo mergedMemo = em.merge(memo);
System.out.println("em.contains(memo) = " + em.contains(memo)); // false
System.out.println("em.contains(mergedMemo) = " + em.contains(mergedMemo)); // true
위의 `memo`는 비영속 상태이지만, `mergedMemo`는 영속 상태이다. 해당 차이를 인지해볼 것.
2. `remove()`
remove(entity): 삭제하기 위해 조회해온 영속 상태의 Entity를 파라미터로 전달받아 삭제 상태로 전환한다.
앞서 한번 했으니 pass
모든 내용을 읽고 맨 위의 사진을 한 번 더 살펴보는 것을 추천드린다.