flush()도 현재 영속 컨텍스트에 있는 엔티티를 DB에 저장하고, commit()도 현재 영속 컨텍스트에 있는 엔티티를 DB에 저장하지않나? 이 둘은 뭐가 다른거지?
한번 이 둘의 차이점에 대해서 알아보자.
@Transactional
@Override
public void flush() {
entityManager.flush();
}
flush는 영속성 컨텍스트의 변경 내용을 DB에 반영하는 것을 말한다.
저번 글에서 잠깐 다뤘었던 쓰기 지연 저장소에 쌓여있던 Insert, Update, Delete SQL들이 flush()시에 DB에 날라간다.
이 때 명시를 해야할 것은 flush는 영속성 컨텍스트를 비우는 것이 아니라 영속성 컨텍스트와 DB의 상태를 맞추는 작업이다.
flush는 영속성 컨텍스트를 비우는 것이 아니라 영속성 컨텍스트와 DB의 상태를 맞추는 작업이다.
단 Commit 시에는 실제 DB에 반영 후 영속 컨텍스트를 비운다.

flush는 commit시 쓰기 지연 SQL 저장소에 등록된 쿼리를 DB로 전송한다.
또한 변경 감지(Dirty Checking)시에는 아래와 같이 동작한다.

스냅샷으로 같이 저장한다.일단 flush와 flush()의 차이를 알 필요가 있다.
간략하게 이야기하면 flush는 쓰기 지연 저장소에 등록된 쿼리를 DB에 전송하는 것을 의미한다.
그리고 flush()는 Entity와 스냅샷 비교, 비교 후 UPDATE를 쓰기 지연 SQL 저장소에 등록, 그리고 flush까지 포함하는 과정을 일컫는다.
즉 flush는 flush()의 한 과정이다.
flush는 또한 롤백이 가능하다.
롤백이 가능한 이유는 아직 commit이 이루어지지 않았기 때문이다.
그렇다면 commit은 무엇일까?
commit은 트랜잭션의 모든 변경 내용을 데이터베이스에 영구적으로 반영한다.
commit은 내부적으로 flush를 수행한 후 트랜잭션을 끝내는 역할이다.
그렇기에 commit은 롤백이 불가능하다.
즉 flush는 물품 구매(환불이 가능한)이고, commit은 최종 구매 확정(환불이 불가능 한)이다.
@Transactional 어노테이션안에서 일어나는 쿼리들 중 한개라도 실패하면, rollback을 수행하고 모든 쿼리들이 성공하면 해당 쿼리들을 모두 commit한다.
JPA를 이해할 때 영속 흐름만 파악하면, 절반은 가는 것 같다.
영속 개념에 대해서 더 깊게 공부하자.