인프런 - 자바 ORM 표준 JPA 프로그래밍 - 기본편 강의노트
플러시란?
영속성 컨텍스트의 변경내용을 데이터베이스에 반영하는 것!
트랜잭션이 커밋될 때 플러시가 일어난다. 영속성 컨텍스트의 쿼리를 DB에 날려준다.
플러시가 발생되면 어떤 일이 일어나는가?
변경 감지가 일어남. 수정된 엔티티에 대하여 쓰기 지연 SQL 저장소에 쿼리가 등록된다.등록된 쿼리를 DB에 전송(등록, 수정, 삭제 쿼리)
플러시가 발생한다고 해서 DB 트랜잭션이 커밋되는 것은 아니다.
영속성 컨텍스트를 플러시하는 방법
직접 쓸 일은 없는데 테스트해보려면 알아야 한다.
1. em.flush() > 직접 호출
Member member = new Member(200L, "member200");
em.persist(member);
em.flush();
System.out.println("====================================");
tx.commit();
원래 em.flush()가 없었다면 트랜잭션을 commit할 때, 쿼리가 날아가는데 flush()를 해주면 그 시점에서 바로 쿼리가 날아가는 것을 볼 수 있다.
flush()를 써도 1차 캐시는 지워지지 않고 그대로 유지가 된다! 영속성 컨텍스트가 비워지는게 아님.
변경감지를 하고 쓰기 지연 SQL 저장소에 있는 쿼리들을 DB에 반영하는 것. 그 외에 뭔가가 일어나지는 않음.
2. 트랜잭션 커밋 > 플러시 자동 호출
3. JPQL 쿼리 실행 > 플러시 자동 호출
JPQL 쿼리 실행시 플러시가 자동으로 호출되는 이유!
JPQL 쿼리 실행시 플러시가 자동으로 호출이 되지 않는다고 가정해보자. 다음과 같이 코드를 실행시켰다고 가정하면,
memberA와 memberB와 memberC는 아직 트랜잭션이 커밋되지 않은 상황이므로 쿼리가 날아가지 않았다. 즉 DB에는 반영이 안 된 상황이다. 그런데 Member 모두를 불러온다면 memberA, memberB, memberC는 DB에 없으므로 members에는 A, B, C가 없는 상황이 될 것이다. 이렇게 하면 문제가 일어날 수 있다. 그렇기 때문에 JPQL 쿼리 실행시 플러시를 호출하여 그 전 내용을 DB에 반영하고 쿼리를 실행시키는 것.
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.setFlushMode(FlushModeType.COMMIT)
FlushModeType.AUTO
커밋이나 쿼리를 실행할 때 플러시(기본값)
FlushModeType.COMMIT
커밋할 때만 플러시
위의 JPQL 쿼리 실행시 플러시가 자동으로 호출되는 이유의 예시 코드에서
내가 만약 지금 DB에 저장할 A, B, C 외의 멤버를 보고 싶었다면? 그렇다면 오히려 JPQL 실행시 날리는 쿼리가 방해가 될 수 있다.
또는 그 전의 쿼리들이 Member와 관계가 없는 코드였다면? 그렇다면 굳이 flush를 해줄 필요가 없다. 그럴 때 옵션을 변경해 줄 수 있다. > 하지만 가급적 손을 안 대는 것을 추천!
플러시는!
영속성 컨텍스트를 비우지 않는다.(이름 때문에 오해하지 말 것!)
영속성 컨텍스트의 변경내용을 데이터베이스에 동기화
트랜잭션이라는 작업 단위가 중요 -> 커밋 직전에만 동기화하면 됨
※ JPA는 동시성에 관한 것은 다 DB 트랜잭션에 위임을 해서 쓴다 -> ? 참고로 알아 놓을 것.
'STUDY > JPA' 카테고리의 다른 글
[4-1] JPA - DDL 자동 생성 (0) | 2023.07.07 |
---|---|
[3-4] 준영속 상태 (0) | 2023.07.06 |
[3-2] 영속성 컨텍스트의 이점 (+Batch) (0) | 2023.07.04 |
[3-1] 영속성 컨텍스트란? (0) | 2023.07.03 |
[2-1] JPA 시작하기 (0) | 2023.06.30 |