❑ 플러시(flush)
1. 플러시의 개념
- 플러시는 영속성 컨텍스트의 변경 내용을 DB에 반영한다
- 플러시라는 이름으로 인해 영속성 컨텍스트에 보관된 엔티티를 지운다고 생각하면 안된다. 영속성 컨텍스트의 변경 내용을 DB에 동기화하는 것이 플러시다.
[참고] Clear
- 플러시를 하면 영속성 컨텍스트의 변경 내용을 DB에 반영(동기화)한다. 하지만 여전히 영속성 컨텍스트 내에는 기존에 보관된 엔티티 등의 정보가 캐시로 남아있다
- Clear는 영속성 컨텍스트의 캐시를 전부 제거하는 역할을 해준다.
2. 플러시를 실행할 경우 구체적인 동작
- 영속성 컨텍스트에 있는 모든 엔티티를 스냅샷과 비교해 수정된 엔티티를 찾는다. 수정된 엔티티는 수정 쿼리를 만들어 쓰기 지연 SQL저장소에 등록한다
- 쓰기 지연 SQL 저장소의 쿼리를 DB에 전송한다(CREATE, UPDATE, DELETE 쿼리)
❑ 플러시하는 세 가지 방법
1. 엔티티 매니저(EntityManger)의 flush()를 직접 호출
- 엔티티 매니저의 flush() 메소드를 직접 호출해 영속성 컨텍스트를 강제 플러시할 수 있다
- 테스트나 다른 프레임워크와 JPA를 함께 사용할 때를 제외하곤 거의 사용하지 않음
2. 트랜잭션 커밋 시 플러시 자동 호출
- 변경 내용을 SQL로 DB에 전달하지 않고 트랜잭션만 커밋하면 DB에 변경사항이 반영되지 않는다
- 따라서 트랜잭션 커밋 전 꼭 플러시를 통해 영속성 컨텍스트의 변경 내용이 DB에 반영되어야 한다.
- JPA는 이런 문제를 예방하기 위해 트랜잭션을 커밋할 때 플러시를 자동으로 호출한다
3. JPQL 쿼리 실행 시 플러시 자동 호출
- JPQL와 같은 객체지향 쿼리를 호출할 때도 플러시가 자동 실행된다
- 아래 Example Code를 통해 그 이유에 대해 살펴본다
Example Code
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();
- em.persist()를 통해 memberA, B, C는 영속 상태가 되었다. 하지만 해당 엔티티들은 영속성 컨텍스트에는 있지만 아직 DB에 반영된 상태는 아니다.
- 이 상태에서 JPQL을 실행할 경우 SQL로 변환되어 DB에서 각 테이블을 조회하게 되는데, memberA, B, C가 영속성 컨텍스트에만 있다면 조회될 수 없다. 이러한 이유에서 JPA는 JPQL을 실행하기 전 플러시를 자동 호출해 변경 내용을 DB에 먼저 반영한다
- 참고로, 식별자를 기준으로 조회하는 find() 메서드를 호출할 때는 플러시가 실행되지 않는다
[참고] 플러시 모드 옵션
- 엔티티 매니저에 플러시 모드를 직접 지정하려면 javax.persistence.FlushModeType을 사용한다
- FlushModeType.AUTO: 커밋이나 쿼리를 실행할 때 플러시(Default 값)
- FlushModeType.COMMIT: 커밋할 때만 플러시
예시) em.setFlushMode(FlushModeType.COMMIT)
❑ @Transactional
- 스프링 프레임워크는 @Transactional 어노테이션이 붙어 있는 클래스나 메소드에 트랜잭션을 적용한다.
- 외부에서 이 클래스의 메소드를 호출할 때 트랜잭션을 시작하고, 메소드를 종료할 때 트랜잭션을 커밋한다.
(트랜잭션을 커밋한다는 것은 영속성 컨텍스트를 플러시 한다는 의미이기도 하다) - @Transactional(readOnly = true) 옵션을 적용할 경우 영속성 컨텍스트를 플러시하지 않는다
(*readOnly = false가 디폴트) - 만약 예외가 발생하면 트랜잭션을 롤백한다. 참고로, @Transactional은 RuntimeException과 그 자식들인 언체크(Unchecked) 예외만 롤백한다. 만약 체크(Checked) 예외가 발생해도 롤백하고 싶다면 @Transactional(rollbackFor = Exception.class)와 같이 예외를 지정해야 한다.
❑ Reference
자바 ORM 표준 JPA 프로그래밍 | 김영한 | 에이콘 출판
'Back-End > JPA' 카테고리의 다른 글
[Spring] JPA를 사용한 MySQL 연동(생성/조회) 예제 (0) | 2021.07.19 |
---|