작성
·
293
1
안녕하세요 !! 마지막 부분 궁금한 점이 생겨서 질문드립니다.
벌크를 사용하면 db에 바로 때려버린다고 하셨는데,
//given
~~~~~ 5개
//when
int resultCount=memberRepository.bulkAgePlus(20);
em.flush();
em.clear();
이 상황에서 먼저 벌크연산을 통해 db 값을 수정을 하고, flush와 clear 연산을 하게되는데, 이 상황에서의 flush 연산의 동작이 궁금합니다.
책에 따르면, 변경 감지가 동작해서 영속성 컨텍스트에 있는 모든 엔티티를 스냅샷과 비교해서 수정된 엔티티를 찾는다. 수정된 엔티티는 수정 쿼리를 만들어 쓰기 지연 SQL 저장소에 등록한다. 이 쿼리를 db에 전송한다. 라고 나와 있습니다.
먼저, save를 하는 과정에서 persist 한 member들 중 20이 넘는 것들은
member3 20
member4 21
member5 40
이 있습니다. persist 이후 bulk연산으로 db에 바로 값을 변경시키고, flush에 들어서게 되면
스냅샷 자체는 20,21,40 으로 되어있고 영속성컨텍스트에 따로 값을 변경하지 않았으니 수정된 엔티티를 찾지 못하고, 수정쿼리를 만들어서 지연 SQL 저장소에 등록하지도 않았을 것이고, 이곳에 등록된 것이 없으니 db에 전송하는 쿼리문도 없기 때문에 bulk 연산으로 수정된 값이 남게 되는 것인가요 ?
그렇다면 이 부분에서 flush는 스냅샷과의 비교를 했을 뿐 변경된 엔티티를 감지하지 못하였기 때문에 사실상 비교의 역할만 했다고 볼 수 있는건가요?
제가 이해한게 맞나 궁금합니다!! 긴 질문 읽어주셔서 감사합니다.
답변 4
5
안녕하세요. kangsy763님^^
이해하신게 맞습니다^^
그리고 한가지 더 말씀드리면 사실 마지막에 플러시를 꼭 호출하지 않아도 됩니다. 왜냐하면 벌크연산도 JPQL이기 때문입니다. JPQL을 실행하면 실행 직전에 자동으로 플러시가 호출됩니다.
int resultCount=memberRepository.bulkAgePlus(20); // 여기서 벌크연산 실행 직전에 em.flush()가 호출됩니다.
em.flush();
뒤에 em.flush();를 적어둔 것은 혹시라도 기본편을 아직 안보고 JPQL 실행 직전에 플러시가 호출되는 내용을 잘 모르시는 분들의 이해를 돕기 위해 적어두었습니다.
도움이 되셨길 바라며, 감사합니다.
2
어이쿠 칭찬 감사합니다. ㅋㅋㅋㅋㅋ
추가로 궁금해하신 부분은 사실 새로운 객체기 때문에 비교할 대상이 없습니다. 따라서 스냅샷과 비교라는 표현보다는 그냥 새로운 객체를 인식해서 DB에 저장한다고 이해하시면 됩니다.
1
아 한 가지 더 궁금한 점이 있는데, 플러시가 변경 감지 동작해서 스냅샷과 비교를 하는 것인데..
기존에 영속성 컨텍스트에 아무것도 없다가 persist를 통해서 들어오게 된 경우에는 영속성 컨텍스트의 변경이 일어났기 때문에 db에 등록이 되는거라고 생각이 드는데, 이 경우에도 스냅샷과 비교를 한다고 말을 할 수가 있나요 ?
1