Java/JPA

JPA - 플러시, 준영속 상태

ta_chan 2023. 9. 20. 21:31

1. 플러시

플러시란 영속성 컨텍스트의 변경내용을 데이터베이스에 반영하는것을 의미한다.

 

플러시가 일어나면 어떤일이 일어나는가?

1. 변경감지가 일어난다. 그리고

2. 수정된 엔티티의 쿼리를 지연 SQL 저장소에 등록한다. 그리고

3. 쓰기 지연 SQL 저장소의 쿼리를 데이터베이스에 전송한다.

4. 플러시를 보낸다고 해서 커밋이 되는것은 아니다.

 

영속성 컨텍스트를 플러시하는 방법

em.flush() - EntityManager의 flush를 직접 호출하는 방법.

member200이라는 맴버객체를 생성하고, em.persist를 한다고 하면,

현재 member 객체는 영속성 컨텍스트, 즉 1차 캐시에 저장된 상태이다.

또 동시에 지연 SQL 저장소에 객체를 생성하는 쿼리가 저장된다.

이후 em.flush()를 하게 되면 

트랜잭션이 커밋되기 전에 member 생성 쿼리가 데이터베이스에 호출된다.

 

트랜잭션 커밋 - 트랜직션을 커밋하면 자동으로 플러시가 호출.

위 코드처럼 따로 flush를 호출하지 않는다면 실제 플러시가 실행되는 시점은 커밋이 실행되는 시점이다.


JPQL 쿼리 실행 - 플러시 자동 호출

JPA 기본설정이 JPQL을 실행하면 무조건 플러시가 호출되게 되어있다.

플러시의 모드옵션을 설정해서 변경할 수 있지만, 크게 도움이 되지 않는다고 한다.

 

정리

1. 플러시는 영속성 컨텍스트를 비우지 않는다.

2. 플러시는 영속성 컨텍스트의 변경내용을 데이터베이스에 동기화 한다.
3. 트랜잭션이라는 작업 단위가 중요하기 때문에 커밋 직전에만 동기화 하면 된다.

 

2. 준영속 상태

영속 -> 준영속

영속 상태의 엔티티가 영속성 컨텍스트에서 분리(detatched)되는 것
영속성 컨텍스트가 제공하는 기능을 사용 못한다.

준영속 상태로 만드는 방법

em.detach(entity); 

특정 엔티티만 준영속 상태로 전환한다.

150번 객체를 em.find로 찾았다. 이렇게되면 영속성컨텍스트에 150번 맴버객체가 등록된다.

이후 맴버의 이름을 "AAAA"로 변경했다. 

본래대로라면 커밋이 되었을 때 JPA에서 변경감지가 일어나 업데이트 쿼리가 생성되어야 정상이지만

현재는 em.detach를 사용하여 맴버 엔티티를 준영속 상태로 전환했다. 즉 영속성 컨택스트에서

맴버 엔티티를 빼내었다는 이야기이므로 em.detach(member)가 일어난 시점 이후로에는

영속성 컨텍스트에 맴버 객체가 없으므로 변경감지가 일어나지 않고

결론적으로 조회 쿼리만 남게 되는 것이다.

 

em.close();

영속성 컨텍스트를 완전히 초기화시킨다.

em.detach(entity)와 같은 결과를 반환한다.

 

em.close();

영속성 컨텍스트를 종료시킨다.

위와 동일.