주의사항
flush가 발생한다고 해서 commit이 이루어지는 것은 아님
실제 순서는 flush -> commit 순
플러시가 동작할 수 있는 이유는 데이터베이스 트랜젝션(작업 단위)라는 개념이 있기 때문이다. 트랜젝션이 시작되고 해당 트랜젝션이 commit되는 시점 직전에만 동기화(변경 내용을 날림) 해주면 되기 때문에 그 사이에 플러시 메커니즘이 동작한다.
JPA의 기본모드는 JPQL 쿼리 실행 시 flush()를 자동으로 날린다.
em.persist(memberA);
em.persist(memberB);
em.persist(memberC);
query = entityManager.createQuery("select m from Member m", Member.class);
List<Member> members = query.getResultList();
원래 member A,B,C를 영속성 컨텍스트에 저장한 상태에서 바로 조회하면 조회가 되지 않는다. 왜냐하면 영속성 컨텍스트에 저장했다고 해서 DB에 바로 저장되는 것이 아니라 flush 와 commit 과정을 통해 DB에 insert가 이루어져야 DB상에 저장이 되고 그 이후에 조회가 가능하기 때문이다.
그러나 위 코드는 createQuery로 JPQL 쿼리를 실행한다.
JPQL 쿼리 실행 시 flush와 트랜젝션 커밋은 자동으로 호출되기 때문에 위 코드는 조회가 가능해진다.
참고
QueryDSL 역시 JPQL 빌더 역할을 해주는 것이기 때문에 QueryDSL 실행 시에도 당연히 플러시와 트랜젝션 커밋은 자동 호출된다.
flush : 영속성 컨텍스트에 있는 엔티티 정보를 DB에 동기화하는 작업. 아직 트랜잭션 commit이 안돼서 에러 발생시 롤백 가능
transaction commmit : transaction commit 이후에는 DB에 동기화된 정보가 영구히 반영되어 롤백을 할 수 없다.
보통 Repository를 만들 때 Spring-Data-Jpa의 JpaRepository 인터페이스를 상속받는다.
이 때 JpaRepository 의 기본 구현체는 SimpleJpaRepository 이며 SimpleJpaRepository의 클래스에는 @Transactional 어노테이션이 붙어 있으므로 해당 클래스에 있는 메소드들은 모두 트랜잭션에 걸리게 된다.
해당 클래스에 있는 메소드들이 모두 트랜젝션에 걸린다는 것은 다시말해, 클래스의 메소드가 성공적으로 return 하게 되면 Transaction Commit 도 이루어지게 된다.
JPaRepository 인터페이스 상속을 받지 않더라고 클래스에 @Transactional 어노테이션을 붙이게 되면 해당 클래스의 메소드 실행 return 후 Transaction Commit 이 실행된다.