해결된 질문
작성
·
785
·
수정됨
3
안녕하세요 영한님!
이번 강의로 Modifying 어노테이션의 clearAutomatically 옵션이 왜 필요한건지 잘 이해했습니다. 그런데 다른 옵션인 flushAutomatically는 제가 아는 상식과 충돌이 되서 질문드립니다.
기본적으로 createQuery를 날리면 db에 직접 접근하여 처리하기 때문에 현재 영속성 컨텍스트의 1차 캐시에 있는 것들을 강제로 flush하고 작성한 쿼리를 날리는 것으로 이해를 하고 있습니다.
벌크연산 역시 createQuery의 일종이라고 생각하기 때문에 flushAutomatically 옵션의 기본값은 true일 거라고 예상했는데 false로 되어있어서 헷갈립니다.
1. Modifying에서 제공하는 자동 flush 옵션과 벌크 연산전에 자동으로 일어나는 flush는 의미가 서로 다른건가요?
//추가: 구글링을 해본 결과, 두 flush는 같은 의미가 맞고 @Modifying 옵션 값과 상관없이 hibernate에서 강제로 flush를 해준다고 합니다.
그리고 이건 질문은 아니고 제가 정리한게 맞는지 여쭤봅니다.
강의 영상처럼 테스트 클래스의 한 @Transaction 안에서 멤버를 생성하고 벌크연산으로 변경하고 조회하는 것이 아니라
서비스 레이어에서 각각의 @Transaction가 있는 메서드로 분리해서 테스트를 해봤는데, 여전히 동일한 현상이 일어나더라구요.
2. 이것은 OSIV에 의해서 영속성 컨텍스트의 생명주기가 트랜잭션의 종료시점이 아닌 최종적으로 response를 뱉을때까지 유지되고, 1차 캐시 역시 유지되기 때문에 각각의 트랜잭션에서 실행되는 서비스 메서드 간에서도 1차 캐시가 공유된다는 뜻으로 이해하면 될까요?
답변 2
3
안녕하세요. Young.K님
해당 기능이 들어간 commit을 통해서 flushAutomatically를 이해할 수 있는데요.
https://github.com/spring-projects/spring-data-jpa/issues/1167
하이버네이트는 내부에 최적화 기능이있습니다.
JPQL을 실행할 때 사실 모든 내용을 다 플러시 하는 것이 아니라, 해당 JPQL과 관련 있는 엔티티만 플러시합니다.
이 상태에서 clearAutomatically가 실행되면 플러시 되지 않은 내용에 문제가 발생할 수 있습니다.
추가로 하이버네이트에 옵션으로 JPQL 실행시 강제로 플러시가 되지 않도록 설정할 수도 있는데요. 이 경우에도 문제가 될 수 있을 것 같아요.
그래서 flushAutomatically 옵션이 들어갔습니다. 이 옵션은 모든 내용을 다 플러시해서 clearAutomatically로 인한 문제를 방지합니다.
2번 질문은 내용을 정확히 이해하지 못했습니다. 자세히 설명해주시겠어요?
감사합니다.
0
감사합니다! 그런 차이가 있는지도 모르고 잘못 이해하고 넘어갈뻔 했네요.
2번 질문은 의사코드로 설명드리면
@Transaction
Member method1() {
멤버생성();
벌크수정();
Member member = 멤버조회();
return member;
}
Member method2() {
@Transaction 멤버생성();
@Transaction 벌크수정();
Member member = @Transaction 멤버조회();
return member;
}
위의 method1처럼 하나의 트랜잭션 범위에서 작업하는 것이 아니라
method2처럼 트랜잭션이 분리된 상황이면 1차캐시가 각각의 트랜잭션이 끝나는 시점에 없어져서 멤버를 조회할 때 db에서 새로 select해서 가져올줄 알았는데 아니더라구요.
그래서 이건 OSIV에 의해서 1차캐시가 요청이 종료될때까지 없어지지 않고 계속 살아있기 때문이다. 라고 이해를 했는데 맞는지 궁금합니다!
네 맞습니다^^