일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 | 31 |
- Java
- Baekjoon
- Spring
- spring boot
- 코드
- 코딩
- 엘라스틱서치
- 그리디
- 프레임워크
- JPA
- 백준
- 자바
- cleancode
- 코딩테스트
- API
- 스프링
- 개발자
- 애자일기법
- Elasticsearch
- ES
- 읽기쉬운코드
- 개발
- 클린코드
- framework
- 애자일프로그래밍
- database
- 데이터베이스
- 그리디알고리즘
- 애자일
- 알고리즘
- Today
- Total
튼튼발자 개발 성장기🏋️
Entity와 영속성 #3 본문
플러시
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' 카테고리의 다른 글
영속성 관리 (0) | 2024.08.17 |
---|---|
Entity 매핑 #1 (0) | 2021.01.13 |
Entity와 영속성 #2 (0) | 2020.11.29 |
Entity와 영속성 #1 (0) | 2020.11.29 |
JPA를 사용하기 위한 설정과 동작 원리 (0) | 2020.09.29 |