[JPA TIL] 플러시(Flush)와 Transaction commit

Hyebin Lee·2021년 12월 4일
2

JPA TIL

목록 보기
1/7
post-thumbnail

플러시(flush)

  • 영속성 컨텍스트의 변경 내용을 DB에 반영
  • Transaction commit 이 일어날 때 flush가 동작, 이때 쓰기 지연 저장소에 쌓아 놨던 INSERT, UPDATE, DELETE SQL들이 DB로 날라감.
  • 그렇다고 영속성 컨텍스트를 비우는 것이 아님
  • 영속성 컨텍스트에 변경된 내용을 DB에 업데이트 하는 작업 (쓰기 지연 SQL을 날려서)

플러시의 동작 과정

  1. 변경을 감지한다 (Dirty Checking)
  2. 수정된 Entity를 쓰기 지연 SQL 저장소에 등록한다.
  3. 쓰기 지연 SQL 저장소의 Query를 DB에 전송한다 (CUD Query)

주의사항

flush가 발생한다고 해서 commit이 이루어지는 것은 아님
실제 순서는 flush -> commit 순
플러시가 동작할 수 있는 이유는 데이터베이스 트랜젝션(작업 단위)라는 개념이 있기 때문이다. 트랜젝션이 시작되고 해당 트랜젝션이 commit되는 시점 직전에만 동기화(변경 내용을 날림) 해주면 되기 때문에 그 사이에 플러시 메커니즘이 동작한다.

JPQL 쿼리 실행시 플러시+트랜젝션 커밋 자동 호출

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 실행 시에도 당연히 플러시와 트랜젝션 커밋은 자동 호출된다.

Q. 왜 JPQL 실행 시 플러시와 트랜젝션 커밋이 실행되도록 했을까?

flush 와 Transaction Commit

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 이 실행된다.

0개의 댓글