시뻘건 개발 도전기

Entity와 영속성 #3 본문

API/JPA

Entity와 영속성 #3

시뻘건볼때기 2020. 11. 29. 20:13
반응형

플러시

  flush는 영속성 컨텍스트의 변경 내용을 데이터베이스에 반영하는 역할을 한다. 이 기능을 사용하면 다음과 같은 일이 일어난다.

- Entity와 영속성 #2에서 알아봤던 것 처럼 변경 감지가 작동하여 스냅샷과 비교하여 수정된 엔티티를 찾는다. 수정된 엔티티가 있을 때 수정 쿼리를 만들어 SQL 저장소에 등록한다.

- SQL 저장소의 쿼리를 데이터베이스에 전송한다.

  영속성 컨텍스트를 플러시하는 방법은 3가지가 있다.

1. em.flush()를 직접 호출한다.

- 테스트나 다른 프레임워크와 JPA를 함께 사용할 때 외에는 거의 사용하지 않는다.

2. 트랜잭션을 커밋하여 플러시를 자동 호출한다.

- 변경 내용을 SQL로 전달하지 않고 커밋하면 데이터베이스에 반영이 되지 않는다.

- 꼭 커밋 전에 영속성 컨텍스트에 변경 내용을 반영해야하기 때문에 자동으로 호출한다.

3. JPQL 쿼리 실행 시 플러시가 자동 호출된다.

- find()를 호출할 때는 플러시가 호출되지 않는다.

 

 

플러시 모드 옵션

  엔티티 매니저에 플러시 모드를 직접 지정할 때 javax.persistance.FlushModeType을 사용한다.

em.setFlushMode(FlushModeType.AUTO);
em.setFlushMode(FlushModeType.COMMIT);

- FlushModeType.AUTO : 커밋이나 쿼리를 실행할 때 플러시 (default)

- FlushModeType.COMMIT : 커밋할 때만 플러시

 

 

준영속

  영속상태에서 준영속 상태일 때의 변화를 살펴보자.

준영속 상태의 엔티티는 영속성 컨텍스트가 제공하는 기능을 사용할 수 없다. 영속 엔티티를 준영속 엔티티로 만드는 방법은 3가지가 있다.

// 첫 번째 방법
em.detach(member);
// 두 번째 방법
em.clear();
// 세 번째 방법
em.close();

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

2. 영속성 컨텍스트 초기화

3. 영속성 컨텍스트 종료

 

detach()

Member member = new Member();
member.setName("dotori");

em.persist(member); // 영속
em.detach(member); // 준영속

tx.commit();

detach()를 한 순간 영속성 컨텍스트에게 해당 엔티티는 더 이상 관리하지 말라는 의미가 된다. 즉, 1차 캐시부터 SQL 저장소까지 모든 정보가 제거된다. 그 말은 커밋이 되어도 데이터베이스에 반영이 되지 않는다는 말이 된다.

 

clear()

Member dotori = em.find(Member.Class, "dotori");


em.clear(); // 준영속

dotori.setName("maeng");

tx.commit();

상위 코드 또한 커밋이 되어도 dotori의 name은 변경되지 않을 것이다. 왜냐하면 em.clear()를 호출한 순간 영속성 컨텍스트가 초기화되어서 dotori는 준영속 상태이기 때문이다.

 

close()

Member dotori = em.find(Member.Class, "dotori");

tx.commit();

em.close();

영속성 컨텍스트가 종료되어 비어있는 상태이기 때문에 dotori는 관리되지 않는다. 참고로 개발자가 직접 준영속 상태로 전환하는 일은 드물다고 한다.

 

준영속 상태의 특징

- 거의 비영속 상태에 가깝다.

- 식별자 값을 가지고 있다.

- 지연 로딩을 할 수 없다.

 

 

merge()

  준영속 엔티티를 영속 엔티티로 전환하기 위해서는 merge()를 사용하면 된다. 준영속 엔티티를 받아서 그 정보로 새로운 영속 엔티티를 리턴한다.

Member member = em.merge(dotori); // dotori는 준영속 엔티티

 

merge() 이후에는 다시 영속 상태로 돌아갔기 때문에 커밋이 이루어졌을 때 데이터베이스에 반영이 될 수 있다. 여기서 주의해야할 점은 member와 dotori는 서로 다른 인스턴스라는 것이다. dotori는 계속 준영속 엔티티이고 member가 영속 엔티티다. 그러므로 우리는 member를 수정할 때만 데이터베이스에 반영이 될 것이다. 따라서 안전하게 다음과 같이 재사용을 통해서 진행하는 것이 안전할 수 있다.

dotori = em.merge(dotori);

 

비영속 merge

merge()는 비영속 엔티티도 영속 엔티티로 만들 수 있다.

Member dotori = new Member("dotori");
dotori = em.merge(dotori);
tx.commit();

 

반응형

'API > JPA' 카테고리의 다른 글

Entity 매핑 #1  (0) 2021.01.13
Entity와 영속성 #2  (0) 2020.11.29
Entity와 영속성 #1  (0) 2020.11.29
JPA를 사용하기 위한 설정과 동작 원리  (0) 2020.09.29
JPA란?  (0) 2020.09.24
Comments