간단히 말해서 플러시란?
영속성 컨텍스트의 변경 내용을 데이터베이스에 반영하는 것
플러시 발생
- 변경 감지(Dirty Checking)
- 수정된 엔티티 쓰기 지연 SQL 저장소에 등록
- 쓰기 지연 SQL 저장소의 쿼리를 데이터베이스에 전송 (등록, 수정, 삭제 쿼리)
영속성 컨텍스트를 플러시하는 방법
1. em.flush() : 직접 호출
2. 트랜잭션 커밋 : 플러시 자동 호출 됨
3. SQL 쿼리 실행 : 플러시 자동 호출 됨
혹시 플러시를 하게 되면 1차 캐시가 다 지워지나요?
아닙니다. 1차 캐시는 다 유지가 됨!
오직 영속성 컨텍스트에 있는 쓰기 지연 SQL 저장소의 쿼리를 데이터베이스에 전송함!
혹은 변경 감지에 의해 변경된 내용만 반영되는 과정이다.
JPQL 쿼리 실행시 플러시가 자동으로 호출되는 이유
em.persist(memberA);
em.persist(memberB);
em.persist(memberC);
//중간에 JPQL 실행
query = em.createQuery("select m from Member m", Member.class);
List<Member> members= query.getResultList();
중간에 그냥 쿼리로 조회를 하면 memberA~C는 조회되지 않음
그래서 JPA가 JPQL 쿼리 실행시 자동으로 플러시를 호출한다.
플러시 모드 옵션
FlushModeType.AUTO : 커밋이나 쿼리를 실행할 때 플러시 (기본값)
FlushModeType.COMMIT : 커밋할 때만 플러시 (가끔 사용할 때가 있음, 커밋 후에 플러시 해야할 때만!)
다시 정리하자면 플러시는!
- 영속성 컨텍스트를 비우지 않음
- 영속성 컨텍스트의 변경내용을 데이터베이스에 동기화 하는 것
- 트랜잭션이라는 작업 단위가 중요하다. 그러므로 트랜잭션 커밋 직전에만 동기화 하면 된다.
준영속 상태
영속 상태의 엔티티가 영속성 컨텍스트에서 분리(detached)된 상태.
즉, 영속성 컨텍스트가 제공하는 기능을 사용 못한다.
준영속 상태로 만드는 방법
1. em.detach(entity) : 특정 엔티티만 준영속 상태로 전환한다.
- 해당 엔티티를 관리하지 말라는 것
- 메소드를 호출하는 순간 1차 캐시부터 쓰기 지연 SQL저장소까지 해당 엔티티를 관리하기 위한 모든 정보가 제거
public void testDetached() {
...
// 회원 엔티티 생성, 비영속 상태
Member member = new Member();
member.setId("memberA");
member.setUsername("회원A");
// 회원 엔티티 영속 상태
em.persist(member);
// 회원 엔티티를 영속성 컨텍스트에서 분리, 준영속 상태
em.detach(member);
transaction.commit(); //트랜잭션 커밋
}
2. em.clear() : 영속성 컨텍스트를 초기화해서 해당 영속성 컨텍스트의 모든 엔티티를 "준영속 상태"로 만든다.
//엔티티 조회, 영속 상태
Member member = em.find(Member.class, "memberA");
em.clear(); //영속성 컨텍스트 초기화
//준영속 상태
member.setUsername("changeName");
3. em.close(): 영속성 컨텍스트를 종료하면 해당 영속성 컨텍스트가 관리하던 영속 상태의 엔티티가 모두 준영속 상태가 된다.
public void closeEntityManager() {
EntityManagerFactory emf =
Persistence.createEntityManagerFactory("jpabook");
EntityManager em = emf.createEntityManager();
EntityTransaction transaction = em.getTransaction();
transaction.begin(); // [트랜잭션] - 시작
Member memberA = em.find(Member.class, "memberA");
Member memberB = em.find(Member.class, "memberB");
transaction.commit(); // [트랜잭션] = 커밋
em.close(); // 영속성 컨텍스트 닫기(종료)
}
그러나
개발자가 직접 준영속 상태를 만드는 일은 드물다. 그냥 알아만 두자!
'💻dev > 🌱Java+Spring' 카테고리의 다른 글
JPA | 필드와 컬럼 매핑, 기본 키 매핑 (0) | 2023.04.29 |
---|---|
JPA | 엔티티 매핑 : @Entity, @Table, 데이터베이스 스키마 자동 생성 (0) | 2023.04.27 |
JPA | 엔티티의 생명주기와 영속성 컨텍스트를 알아보자 (0) | 2023.04.27 |
JPA | JPA란 무엇인가? (0) | 2023.04.27 |
Java | 인터페이스(Interface)를 사용하는 이유와 예제 (0) | 2023.04.10 |