영속성 컨텍스트에 쌓인 변경을 SQL로 만들어 DB로 보내는 동작.
commit과 무엇이 다른가 — 자주 틀린다
| flush | commit | |
|---|---|---|
| 하는 일 | 쌓인 SQL을 DB로 전송 | 트랜잭션을 확정 |
| 컨텍스트 | 비우지 않는다 | 종료되며 폐기 |
| 되돌리기 | 아직 롤백 가능 | 불가 |
flush는 "DB에 보냈다"일 뿐 "확정했다"가 아니다. commit은 내부적으로 flush를 먼저 부른다.
flush가 일어나는 순간
em.flush()직접 호출- 트랜잭션 커밋 직전 (자동)
- JPQL 실행 직전 (자동)
3번이 중요하다. 아직 안 보낸 INSERT가 있는데 JPQL로 조회하면 그 데이터가 빠질 수 있으므로, 하이버네이트가 먼저 flush해서 DB 상태와 컨텍스트를 맞춘다.
em.persist(new Member("김")); // 아직 INSERT 안 나감 (쓰기 지연)
em.createQuery("select m from Member m") // ← 여기서 자동 flush → INSERT 실행
.getResultList(); // 방금 넣은 '김'도 결과에 포함
flush 시점에 벌어지는 일 (메모리 → SQL)
다이어그램 로딩 중…
쓰기 지연이란
persist()를 불러도 INSERT가 즉시 나가지 않는다. SQL을 쓰기 지연 저장소(action queue)
에 모아 두었다가 flush 때 한 번에 보낸다. 왕복 횟수를 줄이고 JDBC 배치로 묶을 수 있다.
단 식별자 생성 전략이 IDENTITY면 예외다. auto_increment 값을 알아야 영속성
컨텍스트의 키를 만들 수 있어서 persist() 시점에 INSERT가 곧바로 나간다 — 이 경우
쓰기 지연 이득이 없다.