Java

JPA PersistContext

dev_roach 2021. 11. 22. 20:10
728x90

이 문서는 Hibernate ORM 공식문서를 읽으며 정리한 글입니다.

 

 

Hibernate.Session 과 EntityManager 의 API 는 데이터를 지속성있게 다룰 수 있도록 해주는데 이를 Persistence Context 라 한다.

Persistence Context 에서 관리되는 데이터는 기본적으로 database 와 persistence context 양쪽에서 연관된 상태로 관리된다.

Persistence data 는 아래와 같은 생명주기를 가진다.

LifeCycle

비영속 (transient) : 엔티티가 만들어졌지만 아직까지 Persistence Context 와 연관이 없는 상태를 뜻합니다.

위와 같이 Memer Entity 는 초기화가 됬지만, 아직 영속성 컨텍스트에 관리되지 않고있음을 의미합니다.

 

영속(managed / persistent) : 엔티티가 Persistence Context 와 연관된 상태를 뜻하며 Identifier 로 식별 가능한 상태를 뜻합니다. 데이터 베이스에 있거나 혹은 아직은 없을 수도 있습니다. 

위와 같이 EntityManager 에 Persist 되는 순간 Persistence Context 에 관리됩니다.

 

비영속(detached) : Persistence Context 에서 관리되다가 분리된 것을 뜻합니다.

위와 같이 detach 됬을때는 dirtyChecking 이 안되는 것을 볼 수 있습니다.

즉, 영속성 컨텍스트에 의해 관리가 되지 않기 때문입니다.

아래 관리되고 있을때 예시를 한번 보시죠.

여기서는 정상적으로 update query 가 발생하는 것을 알 수 있습니다.

 

삭제 (removed) : 삭제 상태는 Persistence Context 에 식별자로 관리되고 있다가 삭제된 객체를 뜻합니다. 데이터 베이스에서 또한 삭제 됩니다.

Dirty Checking

Dirty Checking 은 Hibernate 에서 Persistence Context 에 의해 관리되는 Entity 가 변경됬는지 여부를 계산하는 것을 의미한다.

어떻게 Hibernate 는 이걸 알 수 있을까?

그건 바로 Hibernate 는 데이터베이스에서의 엔티티 상태에 대한 마지막 이력을 관리하고 있기 때문이다.

Persistence Context 를 플러시하는 과정에서 하이버 네이트는 관리되는 모든 엔티티에 대하여

"last known database state" 와 다른점이 없는지를 점검한다.

그래서 PC 에 의해 관리되는 많은 수의 엔티티가 있다면, 성능이 저하될 수도 있다. (처음 알았네..) 

 

만약 DataType 의 내부 상태 변경에 신경쓰지 않는다면, Bytecode-EnhanceMent 로 Dirty Checking 를 강화할 수 있다고 한다.

Class 의 바이트 코드를 조작해서 엔티티에 직접 Dirty Checking 을 추적할 수 있다고 한다.

그래서 Flush 시간에 Hibernate 는 diff 를 계산할 필요없이 Entity 에세 변경점을 묻게 된다.

 

흠 Spring Data JPA 는 어떤걸 쓰고 있을꺄? 전자인가..?

일단 컴파일된 Entity 파일에 변경점을 질문할 수 있는 코드가 없는걸 봐서 전자일 거 같다는 생각이 든다.

 

아, 알아보니 이런 설정을 따로 해줘야 된다고 한다.

CascadeType

여기서는 기본적으로 CascadeType.ALL 에 대해서만 언급하려고 한다.

나머지가 궁금하면 미안한데 찾아보길 바란다 ㅠㅠ.. 글이 너무 길어질까봐 궁금한점만 정리하려고 한다.

 

일단 Entity 가 DB 에 올라가기 위해서는 PC 에 의해 관리되야 한다는 점을 깨달았을 것이다.

만약 아래처럼 1:N 관계가 있다고 해보자.

내가 원하는건 Team 의 List 에 Member 를 추가했을때 같이 DB 에 저장되게 하고 싶다.

그렇다면 Team 이 영속화될때 Member 또한 영속화 시켜야 할 것이다.

따라서 아래와 같은 옵션을 줘보자

아래와 같이 테스트를 해보면 잘 통과하는 모습을 확인할 수 있다.

그런데 궁금한 점이 하나 생겼다.

만약에 Team 안의 멤버를 변경해도 변경점을 찾을 수 있을까? 테스트를 해보자.

DB 에 이렇게 있다고 해보자.

결과가 어떨까?

실패하는 모습을 볼 수 있다. 왜일까?

CascadeType.REPLICATE 옵션이 없기 때문이다. 하지만 이것은 공개 옵션으로 따로 나와있지는 않다.

보면 알수 있듯이 ALL 을 쓰면 이를 사용할 수 있다.

그렇다면 옵션을 한번 바꿔보자.

UPDATE Query 가 나가면서 TEST 가 통과했다.

 

728x90

'Java' 카테고리의 다른 글

객체지향 체조  (0) 2021.11.28
객체지향) 객체의 역할, 책임, 협력  (2) 2021.11.24
Java Stream  (0) 2021.11.11
젠킨스 JVM 메모리 설정  (0) 2021.10.20
객체는 무엇일까?  (0) 2021.10.14