당니의 개발자 스토리
준영속 상태 본문
준영속 상태
이번에는 준영속 상태에 대해서 알아보겠습니다.

준영속 상태라는 것은 사실 지금 배워도 크게 이해하기가 쉽지 않아요. 나중에 실전에서 웹 어플리케이션 만들 때 제가 좀 더 자세히 설명 드릴 거고요. 지금은 약간 이런 게 있다 정도만 하시면 됩니다.
이제 영속에서 준영속으로 갈 수 있는 상태가 뭐가 있냐면, 일단em.persist 하면 영속상태가 되죠. 그리고 영속상태가 되는 케이스 하나가 더 있습니다. 뭐가 있냐면 내가 em.find를 해서 DB에서 가져왔단 말이에요. 근데 얘가 영속성 컨텍스트에 없어요.
그러면 보세요.

이 경우에 지금 member2번을 조회해야 되는데 만약에 1차 캐시가 없다고 해봐요. 그러면 DB에서 가져와서 1차 캐시에 올린다고 했죠. 이 1차 캐시에 올라간 상태가 바로 영속상태 거든요. 뭔가 JPA가 관리하는 상태가 된 거죠. 내가 persist 해서 집어 넣을 때도 영속 상태가 되지만 반대로 em.find나 뭔가 JPA를 통해서 조회를 했을 때도 영속성 컨텍스트에 딱 없으면 DB에서 가져와서 1차 캐시에 올리니까 영속 상태가 됩니다.

그러면 준영속 상태라는 건 뭐냐면 영속 상태의 엔티티가 영속성 컨텍스트에서 분리되는 거에요. 한마디로 그냥 다 빼버리는 거에요. 이렇게 되면 영속성 컨텍스트 제공하는 update 할 때 기능이라던가, 뭐 Dirty Checking 이라던가 이런 거 자체를 사용을 못하게 됩니다.
준영속 상태로 만드는 방법은 여러가지가 있는데요.

간단하게 보여드릴게요.

자 이 경우에 105번을 조회해서 이름을 ZZZZ로 바꿨죠.

그러면 얘를 다시 AAAA로 바꿔 볼게요.

그런데 지금 em.find 해서 member를 가져오면 이 member는 지금 영속 상태에요. 가져올 때 jpa가 보니까 '150번이 없네?' 하고, 이 150번을 db에서 조회해 와서 jpa 영속성 컨텍스트에 올립니다.
그리고 값을 변경하니까 Dirty Checking, 변경 내역을 추적해가지고 update 쿼리를

이 시점에 날려줬던 거죠. 그런데 만약에 '아 더 이상 영속성 컨텍스트로 관리하기 싫어' 하면 어떻게 될까요?

자 em.detach, 말 그대로 영속성 컨텍스트에서 이제 떼어낸다는 거죠. 그럼 이제 member를 jpa에서 관리 안 하는 거예요. 그러면 이 트랜잭션을 커밋 할 때 아무도 일어나지 않게 됩니다. 왜냐하면 JPA가 더이상 관리를 안 하니까 쿼리고 뭐고 아무것도 안 날리겠죠. 영속성 컨텍스트에서 그냥 통으로 다 빠져버린 거예요.
실행해 보겠습니다.

보시면 select 쿼리만 나오고 지금 데이터를 변경했는데 update 쿼리가 안 나가죠.

왜냐하면 detach를 했기 때문에 영속성 컨텍스트에서 더이상 관리하지 말라고 해서 다 끄집어낸 거에요.
이거를 사실 내가 직접 쓸 일은 거의 없구요. 나중에 웹 어플리케이션 개발하거나 이럴 때, 좀 복잡할 때는 '아 이게 이래서 되는구나' 하고 이해하실 수 있어요. 지금은 이론적으로 이렇구나. 정도만 알아두시면 됩니다. 그러면 이렇게 영속 상태였다가 영속성 컨텍스트에서 빠진 상태를 이제 준영속 상태라고 해요. detach된 상태라고 얘기하는데 옛날에는 주로 준영속 상태라고 많이 불러서 저도 그렇게 부릅니다. 암튼 이 준영속 상태로 만드는 방법은 뭐냐면,

이겁니다. 특정 엔티티만 준영속 상태로 전환할 때는 이 detach를 쓰면 되구요.

그리고 em.clear()로도 준영속 상태를 만들 수 있는데, 이건 뭐냐면 이 엔티티 매니저 안에 있는 영속성 컨텍스트를 통째로 다 지워버리는 겁니다.
이렇게 해도 아무도 일어나지 않습니다. 돌려보겠습니다.

find로 select query 하고 데이터를 변경했는데 update query가 안나가죠. select 까지는 조회한 거니까 바로 쿼리가 보이는데 영속성 컨텍스트를 통째로 날리면서 커밋할 게 없으니까 tx.commit() 해도 아무것도 안 날라가는 겁니다.

그럼 150L을 다시 조회하면 어떻게 될까요? 똑같은 애를 다시 조회하게 되면, 잘 생각해 보세요.
그러면 영속성 컨텍스트에 1차 캐시를 보고 '150L이 없네' 하고 영속성 컨텍스트에 다시 올려야지. 라고 하겠죠.

그래서 보시면 select 쿼리가 두 번 나갑니다.
영속성 컨텍스트 클리어를 해버리니까 1차 캐시가 통으로 지워진 거고, 다시 150L을 db에 찾아와서 1차 캐시에 올리는 거죠.
그러니까 똑같은 member를 다시 조회해도 이전에 clear()해서 영속성 컨텍스트가 완전 초기화 되어있기 때문에 다시 처음부터 영속성 컨텍스트 올리게 됩니다.
그래서 1차 캐시와 관계없이 테스트 케이스 작성하거나 눈으로 보고 싶을 때 이런 clear 같은 게 도움이 됩니다.

자 그 다음 em.close() 해서 영속성 컨텍스트를 닫아 버려요. 그럼 당연히 member는 더 이상 관리가 안 되겠죠. 데이터를 변경해도 변경이 안 될겁니다. update 쿼리가 안 날라가니까요.
이렇게 이 세 가지 방법으로 엔티티를 준영속성 상태로 만들 수가 있습니다.
나중에 웹 어플리케이션 실제 개발하는 단계에서 응용이 들어가야 이거에 대해서 '아 이래서 이때는 이렇구나' 하고 좀 깊이 아실 수가 있어요.
'스프링 > 자바 ORM 표준 JPA 프로그래밍 - 기본편' 카테고리의 다른 글
| 객체와 테이블 매핑 (0) | 2024.05.27 |
|---|---|
| 정리 (0) | 2024.05.26 |
| 플러시 (0) | 2024.05.26 |
| 영속성 컨텍스트 2 (0) | 2024.05.26 |
| 영속성 컨텍스트 1 (0) | 2024.05.25 |